https://github.com/makslevental updated 
https://github.com/llvm/llvm-project/pull/173439

>From 5f4d2cdf5cf3c487ea7537b352166ff0252e9b89 Mon Sep 17 00:00:00 2001
From: makslevental <[email protected]>
Date: Tue, 23 Dec 2025 12:20:34 -0800
Subject: [PATCH 1/3] try MLIR_PYTHON_API_EXPORTED

---
 mlir/cmake/modules/AddMLIRPython.cmake      |   9 +-
 mlir/include/mlir-c/Support.h               |   2 +
 mlir/include/mlir/Bindings/Python/Globals.h |   4 +-
 mlir/include/mlir/Bindings/Python/IRCore.h  | 121 +++++++++++---------
 mlir/include/mlir/Bindings/Python/IRTypes.h |   3 +-
 5 files changed, 75 insertions(+), 64 deletions(-)

diff --git a/mlir/cmake/modules/AddMLIRPython.cmake 
b/mlir/cmake/modules/AddMLIRPython.cmake
index 0501e0b5e51fe..8ec9304421b54 100644
--- a/mlir/cmake/modules/AddMLIRPython.cmake
+++ b/mlir/cmake/modules/AddMLIRPython.cmake
@@ -854,11 +854,10 @@ function(add_mlir_python_extension libname extname 
nb_library_target_name)
       target_link_options(${libname} PRIVATE "-Wl,-z,undefs")
     endif()
     nanobind_link_options(${libname})
-    target_compile_definitions(${libname} PRIVATE 
NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN})
-    set_target_properties(${libname} PROPERTIES
-      VISIBILITY_INLINES_HIDDEN OFF
-      C_VISIBILITY_PRESET default
-      CXX_VISIBILITY_PRESET default
+    target_compile_definitions(${libname}
+      PRIVATE
+      NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
+      MLIR_CAPI_BUILDING_LIBRARY=1
     )
     if (MSVC)
       set_property(TARGET ${libname} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)
diff --git a/mlir/include/mlir-c/Support.h b/mlir/include/mlir-c/Support.h
index 78fc94f93439e..6abd8894227c3 100644
--- a/mlir/include/mlir-c/Support.h
+++ b/mlir/include/mlir-c/Support.h
@@ -46,6 +46,8 @@
 #define MLIR_CAPI_EXPORTED __attribute__((visibility("default")))
 #endif
 
+#define MLIR_PYTHON_API_EXPORTED MLIR_CAPI_EXPORTED
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/mlir/include/mlir/Bindings/Python/Globals.h 
b/mlir/include/mlir/Bindings/Python/Globals.h
index 2184e7e2dc5ca..112c7b9b0547f 100644
--- a/mlir/include/mlir/Bindings/Python/Globals.h
+++ b/mlir/include/mlir/Bindings/Python/Globals.h
@@ -31,7 +31,7 @@ namespace python {
 
 /// Globals that are always accessible once the extension has been initialized.
 /// Methods of this class are thread-safe.
-class PyGlobals {
+class MLIR_PYTHON_API_EXPORTED PyGlobals {
 public:
   PyGlobals();
   ~PyGlobals();
@@ -117,7 +117,7 @@ class PyGlobals {
   std::optional<nanobind::object>
   lookupOperationClass(llvm::StringRef operationName);
 
-  class TracebackLoc {
+  class MLIR_PYTHON_API_EXPORTED TracebackLoc {
   public:
     bool locTracebacksEnabled();
 
diff --git a/mlir/include/mlir/Bindings/Python/IRCore.h 
b/mlir/include/mlir/Bindings/Python/IRCore.h
index 649dfce22ad35..ceedeb691eb58 100644
--- a/mlir/include/mlir/Bindings/Python/IRCore.h
+++ b/mlir/include/mlir/Bindings/Python/IRCore.h
@@ -52,7 +52,7 @@ class PyValue;
 /// Template for a reference to a concrete type which captures a python
 /// reference to its underlying python object.
 template <typename T>
-class PyObjectRef {
+class MLIR_PYTHON_API_EXPORTED PyObjectRef {
 public:
   PyObjectRef(T *referrent, nanobind::object object)
       : referrent(referrent), object(std::move(object)) {
@@ -111,7 +111,7 @@ class PyObjectRef {
 /// Context. Pushing a Context will not modify the Location or InsertionPoint
 /// unless if they are from a different context, in which case, they are
 /// cleared.
-class PyThreadContextEntry {
+class MLIR_PYTHON_API_EXPORTED PyThreadContextEntry {
 public:
   enum class FrameKind {
     Context,
@@ -167,7 +167,7 @@ class PyThreadContextEntry {
 
 /// Wrapper around MlirLlvmThreadPool
 /// Python object owns the C++ thread pool
-class PyThreadPool {
+class MLIR_PYTHON_API_EXPORTED PyThreadPool {
 public:
   PyThreadPool() {
     ownedThreadPool = std::make_unique<llvm::DefaultThreadPool>();
@@ -190,7 +190,7 @@ class PyThreadPool {
 
 /// Wrapper around MlirContext.
 using PyMlirContextRef = PyObjectRef<PyMlirContext>;
-class PyMlirContext {
+class MLIR_PYTHON_API_EXPORTED PyMlirContext {
 public:
   PyMlirContext() = delete;
   PyMlirContext(MlirContext context);
@@ -271,7 +271,7 @@ class PyMlirContext {
 
 /// Used in function arguments when None should resolve to the current context
 /// manager set instance.
-class DefaultingPyMlirContext
+class MLIR_PYTHON_API_EXPORTED DefaultingPyMlirContext
     : public Defaulting<DefaultingPyMlirContext, PyMlirContext> {
 public:
   using Defaulting::Defaulting;
@@ -283,7 +283,7 @@ class DefaultingPyMlirContext
 /// MlirContext. The lifetime of the context will extend at least to the
 /// lifetime of these instances.
 /// Immutable objects that depend on a context extend this directly.
-class BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED BaseContextObject {
 public:
   BaseContextObject(PyMlirContextRef ref) : contextRef(std::move(ref)) {
     assert(this->contextRef &&
@@ -298,7 +298,7 @@ class BaseContextObject {
 };
 
 /// Wrapper around an MlirLocation.
-class PyLocation : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyLocation : public BaseContextObject {
 public:
   PyLocation(PyMlirContextRef contextRef, MlirLocation loc)
       : BaseContextObject(std::move(contextRef)), loc(loc) {}
@@ -329,7 +329,7 @@ class PyLocation : public BaseContextObject {
 /// are only valid for the duration of a diagnostic callback and attempting
 /// to access them outside of that will raise an exception. This applies to
 /// nested diagnostics (in the notes) as well.
-class PyDiagnostic {
+class MLIR_PYTHON_API_EXPORTED PyDiagnostic {
 public:
   PyDiagnostic(MlirDiagnostic diagnostic) : diagnostic(diagnostic) {}
   void invalidate();
@@ -379,7 +379,7 @@ class PyDiagnostic {
 /// The object may remain live from a Python perspective for an arbitrary time
 /// after detachment, but there is nothing the user can do with it (since there
 /// is no way to attach an existing handler object).
-class PyDiagnosticHandler {
+class MLIR_PYTHON_API_EXPORTED PyDiagnosticHandler {
 public:
   PyDiagnosticHandler(MlirContext context, nanobind::object callback);
   ~PyDiagnosticHandler();
@@ -407,7 +407,7 @@ class PyDiagnosticHandler {
 
 /// RAII object that captures any error diagnostics emitted to the provided
 /// context.
-struct PyMlirContext::ErrorCapture {
+struct MLIR_PYTHON_API_EXPORTED PyMlirContext::ErrorCapture {
   ErrorCapture(PyMlirContextRef ctx)
       : ctx(ctx), handlerID(mlirContextAttachDiagnosticHandler(
                       ctx->get(), handler, /*userData=*/this,
@@ -434,7 +434,7 @@ struct PyMlirContext::ErrorCapture {
 /// plugins which extend dialect functionality through extension python code.
 /// This should be seen as the "low-level" object and `Dialect` as the
 /// high-level, user facing object.
-class PyDialectDescriptor : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyDialectDescriptor : public BaseContextObject {
 public:
   PyDialectDescriptor(PyMlirContextRef contextRef, MlirDialect dialect)
       : BaseContextObject(std::move(contextRef)), dialect(dialect) {}
@@ -447,7 +447,7 @@ class PyDialectDescriptor : public BaseContextObject {
 
 /// User-level object for accessing dialects with dotted syntax such as:
 ///   ctx.dialect.std
-class PyDialects : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyDialects : public BaseContextObject {
 public:
   PyDialects(PyMlirContextRef contextRef)
       : BaseContextObject(std::move(contextRef)) {}
@@ -458,7 +458,7 @@ class PyDialects : public BaseContextObject {
 /// User-level dialect object. For dialects that have a registered extension,
 /// this will be the base class of the extension dialect type. For un-extended,
 /// objects of this type will be returned directly.
-class PyDialect {
+class MLIR_PYTHON_API_EXPORTED PyDialect {
 public:
   PyDialect(nanobind::object descriptor) : descriptor(std::move(descriptor)) {}
 
@@ -471,7 +471,7 @@ class PyDialect {
 /// Wrapper around an MlirDialectRegistry.
 /// Upon construction, the Python wrapper takes ownership of the
 /// underlying MlirDialectRegistry.
-class PyDialectRegistry {
+class MLIR_PYTHON_API_EXPORTED PyDialectRegistry {
 public:
   PyDialectRegistry() : registry(mlirDialectRegistryCreate()) {}
   PyDialectRegistry(MlirDialectRegistry registry) : registry(registry) {}
@@ -497,7 +497,7 @@ class PyDialectRegistry {
 
 /// Used in function arguments when None should resolve to the current context
 /// manager set instance.
-class DefaultingPyLocation
+class MLIR_PYTHON_API_EXPORTED DefaultingPyLocation
     : public Defaulting<DefaultingPyLocation, PyLocation> {
 public:
   using Defaulting::Defaulting;
@@ -511,7 +511,7 @@ class DefaultingPyLocation
 /// This is the top-level, user-owned object that contains regions/ops/blocks.
 class PyModule;
 using PyModuleRef = PyObjectRef<PyModule>;
-class PyModule : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyModule : public BaseContextObject {
 public:
   /// Returns a PyModule reference for the given MlirModule. This always 
returns
   /// a new object.
@@ -551,7 +551,7 @@ class PyAsmState;
 
 /// Base class for PyOperation and PyOpView which exposes the primary, user
 /// visible methods for manipulating it.
-class PyOperationBase {
+class MLIR_PYTHON_API_EXPORTED PyOperationBase {
 public:
   virtual ~PyOperationBase() = default;
   /// Implements the bound 'print' method and helps with others.
@@ -604,7 +604,8 @@ class PyOperationBase {
 class PyOperation;
 class PyOpView;
 using PyOperationRef = PyObjectRef<PyOperation>;
-class PyOperation : public PyOperationBase, public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyOperation : public PyOperationBase,
+                                             public BaseContextObject {
 public:
   ~PyOperation() override;
   PyOperation &getOperation() override { return *this; }
@@ -722,7 +723,7 @@ class PyOperation : public PyOperationBase, public 
BaseContextObject {
 /// custom ODS-style operation classes. Since this class is subclass on the
 /// python side, it must present an __init__ method that operates in pure
 /// python types.
-class PyOpView : public PyOperationBase {
+class MLIR_PYTHON_API_EXPORTED PyOpView : public PyOperationBase {
 public:
   PyOpView(const nanobind::object &operationObject);
   PyOperation &getOperation() override { return operation; }
@@ -758,7 +759,7 @@ class PyOpView : public PyOperationBase {
 /// Wrapper around an MlirRegion.
 /// Regions are managed completely by their containing operation. Unlike the
 /// C++ API, the python API does not support detached regions.
-class PyRegion {
+class MLIR_PYTHON_API_EXPORTED PyRegion {
 public:
   PyRegion(PyOperationRef parentOperation, MlirRegion region)
       : parentOperation(std::move(parentOperation)), region(region) {
@@ -777,7 +778,7 @@ class PyRegion {
 };
 
 /// Wrapper around an MlirAsmState.
-class PyAsmState {
+class MLIR_PYTHON_API_EXPORTED PyAsmState {
 public:
   PyAsmState(MlirValue value, bool useLocalScope) {
     flags = mlirOpPrintingFlagsCreate();
@@ -812,7 +813,7 @@ class PyAsmState {
 /// Wrapper around an MlirBlock.
 /// Blocks are managed completely by their containing operation. Unlike the
 /// C++ API, the python API does not support detached blocks.
-class PyBlock {
+class MLIR_PYTHON_API_EXPORTED PyBlock {
 public:
   PyBlock(PyOperationRef parentOperation, MlirBlock block)
       : parentOperation(std::move(parentOperation)), block(block) {
@@ -836,7 +837,7 @@ class PyBlock {
 /// Calls to insert() will insert a new operation before the
 /// reference operation. If the reference operation is null, then appends to
 /// the end of the block.
-class PyInsertionPoint {
+class MLIR_PYTHON_API_EXPORTED PyInsertionPoint {
 public:
   /// Creates an insertion point positioned after the last operation in the
   /// block, but still inside the block.
@@ -877,7 +878,7 @@ class PyInsertionPoint {
 };
 /// Wrapper around the generic MlirType.
 /// The lifetime of a type is bound by the PyContext that created it.
-class PyType : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyType : public BaseContextObject {
 public:
   PyType(PyMlirContextRef contextRef, MlirType type)
       : BaseContextObject(std::move(contextRef)), type(type) {}
@@ -903,7 +904,7 @@ class PyType : public BaseContextObject {
 /// A TypeID provides an efficient and unique identifier for a specific C++
 /// type. This allows for a C++ type to be compared, hashed, and stored in an
 /// opaque context. This class wraps around the generic MlirTypeID.
-class PyTypeID {
+class MLIR_PYTHON_API_EXPORTED PyTypeID {
 public:
   PyTypeID(MlirTypeID typeID) : typeID(typeID) {}
   // Note, this tests whether the underlying TypeIDs are the same,
@@ -929,7 +930,7 @@ class PyTypeID {
 /// concrete type class extends PyType); however, intermediate python-visible
 /// base classes can be modeled by specifying a BaseTy.
 template <typename DerivedTy, typename BaseTy = PyType>
-class PyConcreteType : public BaseTy {
+class MLIR_PYTHON_API_EXPORTED PyConcreteType : public BaseTy {
 public:
   // Derived classes must define statics for:
   //   IsAFunctionTy isaFunction
@@ -1007,7 +1008,7 @@ class PyConcreteType : public BaseTy {
 
 /// Wrapper around the generic MlirAttribute.
 /// The lifetime of a type is bound by the PyContext that created it.
-class PyAttribute : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyAttribute : public BaseContextObject {
 public:
   PyAttribute(PyMlirContextRef contextRef, MlirAttribute attr)
       : BaseContextObject(std::move(contextRef)), attr(attr) {}
@@ -1033,7 +1034,7 @@ class PyAttribute : public BaseContextObject {
 /// Represents a Python MlirNamedAttr, carrying an optional owned name.
 /// TODO: Refactor this and the C-API to be based on an Identifier owned
 /// by the context so as to avoid ownership issues here.
-class PyNamedAttribute {
+class MLIR_PYTHON_API_EXPORTED PyNamedAttribute {
 public:
   /// Constructs a PyNamedAttr that retains an owned name. This should be
   /// used in any code that originates an MlirNamedAttribute from a python
@@ -1059,7 +1060,7 @@ class PyNamedAttribute {
 /// concrete attribute class extends PyAttribute); however, intermediate
 /// python-visible base classes can be modeled by specifying a BaseTy.
 template <typename DerivedTy, typename BaseTy = PyAttribute>
-class PyConcreteAttribute : public BaseTy {
+class MLIR_PYTHON_API_EXPORTED PyConcreteAttribute : public BaseTy {
 public:
   // Derived classes must define statics for:
   //   IsAFunctionTy isaFunction
@@ -1149,7 +1150,8 @@ class PyConcreteAttribute : public BaseTy {
   static void bindDerived(ClassTy &m) {}
 };
 
-class PyStringAttribute : public PyConcreteAttribute<PyStringAttribute> {
+class MLIR_PYTHON_API_EXPORTED PyStringAttribute
+    : public PyConcreteAttribute<PyStringAttribute> {
 public:
   static constexpr IsAFunctionTy isaFunction = mlirAttributeIsAString;
   static constexpr const char *pyClassName = "StringAttr";
@@ -1166,7 +1168,7 @@ class PyStringAttribute : public 
PyConcreteAttribute<PyStringAttribute> {
 /// value. For block argument values, this is the operation that contains the
 /// block to which the value is an argument (blocks cannot be detached in 
Python
 /// bindings so such operation always exists).
-class PyValue {
+class MLIR_PYTHON_API_EXPORTED PyValue {
 public:
   // The virtual here is "load bearing" in that it enables RTTI
   // for PyConcreteValue CRTP classes that support maybeDownCast.
@@ -1196,7 +1198,7 @@ class PyValue {
 };
 
 /// Wrapper around MlirAffineExpr. Affine expressions are owned by the context.
-class PyAffineExpr : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyAffineExpr : public BaseContextObject {
 public:
   PyAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr)
       : BaseContextObject(std::move(contextRef)), affineExpr(affineExpr) {}
@@ -1223,7 +1225,7 @@ class PyAffineExpr : public BaseContextObject {
   MlirAffineExpr affineExpr;
 };
 
-class PyAffineMap : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyAffineMap : public BaseContextObject {
 public:
   PyAffineMap(PyMlirContextRef contextRef, MlirAffineMap affineMap)
       : BaseContextObject(std::move(contextRef)), affineMap(affineMap) {}
@@ -1244,7 +1246,7 @@ class PyAffineMap : public BaseContextObject {
   MlirAffineMap affineMap;
 };
 
-class PyIntegerSet : public BaseContextObject {
+class MLIR_PYTHON_API_EXPORTED PyIntegerSet : public BaseContextObject {
 public:
   PyIntegerSet(PyMlirContextRef contextRef, MlirIntegerSet integerSet)
       : BaseContextObject(std::move(contextRef)), integerSet(integerSet) {}
@@ -1265,7 +1267,7 @@ class PyIntegerSet : public BaseContextObject {
 };
 
 /// Bindings for MLIR symbol tables.
-class PySymbolTable {
+class MLIR_PYTHON_API_EXPORTED PySymbolTable {
 public:
   /// Constructs a symbol table for the given operation.
   explicit PySymbolTable(PyOperationBase &operation);
@@ -1317,7 +1319,7 @@ class PySymbolTable {
 
 /// Custom exception that allows access to error diagnostic information. This 
is
 /// converted to the `ir.MLIRError` python exception when thrown.
-struct MLIRError {
+struct MLIR_PYTHON_API_EXPORTED MLIRError {
   MLIRError(llvm::Twine message,
             std::vector<PyDiagnostic::DiagnosticInfo> &&errorDiagnostics = {})
       : message(message.str()), errorDiagnostics(std::move(errorDiagnostics)) 
{}
@@ -1342,7 +1344,7 @@ inline void registerMLIRError() {
       });
 }
 
-void registerMLIRErrorInCore();
+MLIR_PYTHON_API_EXPORTED void registerMLIRErrorInCore();
 
 
//------------------------------------------------------------------------------
 // Utilities.
@@ -1455,7 +1457,7 @@ inline nanobind::object PyBlock::getCapsule() {
 // Collections.
 
//------------------------------------------------------------------------------
 
-class PyRegionIterator {
+class MLIR_PYTHON_API_EXPORTED PyRegionIterator {
 public:
   PyRegionIterator(PyOperationRef operation, int nextIndex)
       : operation(std::move(operation)), nextIndex(nextIndex) {}
@@ -1486,7 +1488,8 @@ class PyRegionIterator {
 
 /// Regions of an op are fixed length and indexed numerically so are 
represented
 /// with a sequence-like container.
-class PyRegionList : public Sliceable<PyRegionList, PyRegion> {
+class MLIR_PYTHON_API_EXPORTED PyRegionList
+    : public Sliceable<PyRegionList, PyRegion> {
 public:
   static constexpr const char *pyClassName = "RegionSequence";
 
@@ -1529,7 +1532,7 @@ class PyRegionList : public Sliceable<PyRegionList, 
PyRegion> {
   PyOperationRef operation;
 };
 
-class PyBlockIterator {
+class MLIR_PYTHON_API_EXPORTED PyBlockIterator {
 public:
   PyBlockIterator(PyOperationRef operation, MlirBlock next)
       : operation(std::move(operation)), next(next) {}
@@ -1563,7 +1566,7 @@ class PyBlockIterator {
 /// Blocks are exposed by the C-API as a forward-only linked list. In Python,
 /// we present them as a more full-featured list-like container but optimize
 /// it for forward iteration. Blocks are always owned by a region.
-class PyBlockList {
+class MLIR_PYTHON_API_EXPORTED PyBlockList {
 public:
   PyBlockList(PyOperationRef operation, MlirRegion region)
       : operation(std::move(operation)), region(region) {}
@@ -1636,7 +1639,7 @@ class PyBlockList {
   MlirRegion region;
 };
 
-class PyOperationIterator {
+class MLIR_PYTHON_API_EXPORTED PyOperationIterator {
 public:
   PyOperationIterator(PyOperationRef parentOperation, MlirOperation next)
       : parentOperation(std::move(parentOperation)), next(next) {}
@@ -1672,7 +1675,7 @@ class PyOperationIterator {
 /// Python, we present them as a more full-featured list-like container but
 /// optimize it for forward iteration. Iterable operations are always owned
 /// by a block.
-class PyOperationList {
+class MLIR_PYTHON_API_EXPORTED PyOperationList {
 public:
   PyOperationList(PyOperationRef parentOperation, MlirBlock block)
       : parentOperation(std::move(parentOperation)), block(block) {}
@@ -1729,7 +1732,7 @@ class PyOperationList {
   MlirBlock block;
 };
 
-class PyOpOperand {
+class MLIR_PYTHON_API_EXPORTED PyOpOperand {
 public:
   PyOpOperand(MlirOpOperand opOperand) : opOperand(opOperand) {}
 
@@ -1754,7 +1757,7 @@ class PyOpOperand {
   MlirOpOperand opOperand;
 };
 
-class PyOpOperandIterator {
+class MLIR_PYTHON_API_EXPORTED PyOpOperandIterator {
 public:
   PyOpOperandIterator(MlirOpOperand opOperand) : opOperand(opOperand) {}
 
@@ -1785,7 +1788,7 @@ class PyOpOperandIterator {
 /// castable from it. The value hierarchy is one level deep and is not supposed
 /// to accommodate other levels unless core MLIR changes.
 template <typename DerivedTy>
-class PyConcreteValue : public PyValue {
+class MLIR_PYTHON_API_EXPORTED PyConcreteValue : public PyValue {
 public:
   // Derived classes must define statics for:
   //   IsAFunctionTy isaFunction
@@ -1843,7 +1846,7 @@ class PyConcreteValue : public PyValue {
 };
 
 /// Python wrapper for MlirOpResult.
-class PyOpResult : public PyConcreteValue<PyOpResult> {
+class MLIR_PYTHON_API_EXPORTED PyOpResult : public PyConcreteValue<PyOpResult> 
{
 public:
   static constexpr IsAFunctionTy isaFunction = mlirValueIsAOpResult;
   static constexpr const char *pyClassName = "OpResult";
@@ -1887,7 +1890,8 @@ getValueTypes(Container &container, PyMlirContextRef 
&context) {
 /// elements, random access is cheap. The (returned) result list is associated
 /// with the operation whose results these are, and thus extends the lifetime 
of
 /// this operation.
-class PyOpResultList : public Sliceable<PyOpResultList, PyOpResult> {
+class MLIR_PYTHON_API_EXPORTED PyOpResultList
+    : public Sliceable<PyOpResultList, PyOpResult> {
 public:
   static constexpr const char *pyClassName = "OpResultList";
   using SliceableT = Sliceable<PyOpResultList, PyOpResult>;
@@ -1940,7 +1944,8 @@ class PyOpResultList : public Sliceable<PyOpResultList, 
PyOpResult> {
 };
 
 /// Python wrapper for MlirBlockArgument.
-class PyBlockArgument : public PyConcreteValue<PyBlockArgument> {
+class MLIR_PYTHON_API_EXPORTED PyBlockArgument
+    : public PyConcreteValue<PyBlockArgument> {
 public:
   static constexpr IsAFunctionTy isaFunction = mlirValueIsABlockArgument;
   static constexpr const char *pyClassName = "BlockArgument";
@@ -1979,7 +1984,7 @@ class PyBlockArgument : public 
PyConcreteValue<PyBlockArgument> {
 /// elements, random access is cheap. The argument list is associated with the
 /// operation that contains the block (detached blocks are not allowed in
 /// Python bindings) and extends its lifetime.
-class PyBlockArgumentList
+class MLIR_PYTHON_API_EXPORTED PyBlockArgumentList
     : public Sliceable<PyBlockArgumentList, PyBlockArgument> {
 public:
   static constexpr const char *pyClassName = "BlockArgumentList";
@@ -2032,7 +2037,8 @@ class PyBlockArgumentList
 /// elements, random access is cheap. The (returned) operand list is associated
 /// with the operation whose operands these are, and thus extends the lifetime
 /// of this operation.
-class PyOpOperandList : public Sliceable<PyOpOperandList, PyValue> {
+class MLIR_PYTHON_API_EXPORTED PyOpOperandList
+    : public Sliceable<PyOpOperandList, PyValue> {
 public:
   static constexpr const char *pyClassName = "OpOperandList";
   using SliceableT = Sliceable<PyOpOperandList, PyValue>;
@@ -2090,7 +2096,8 @@ class PyOpOperandList : public Sliceable<PyOpOperandList, 
PyValue> {
 /// elements, random access is cheap. The (returned) successor list is
 /// associated with the operation whose successors these are, and thus extends
 /// the lifetime of this operation.
-class PyOpSuccessors : public Sliceable<PyOpSuccessors, PyBlock> {
+class MLIR_PYTHON_API_EXPORTED PyOpSuccessors
+    : public Sliceable<PyOpSuccessors, PyBlock> {
 public:
   static constexpr const char *pyClassName = "OpSuccessors";
 
@@ -2138,7 +2145,8 @@ class PyOpSuccessors : public Sliceable<PyOpSuccessors, 
PyBlock> {
 /// elements, random access is cheap. The (returned) successor list is
 /// associated with the operation and block whose successors these are, and 
thus
 /// extends the lifetime of this operation and block.
-class PyBlockSuccessors : public Sliceable<PyBlockSuccessors, PyBlock> {
+class MLIR_PYTHON_API_EXPORTED PyBlockSuccessors
+    : public Sliceable<PyBlockSuccessors, PyBlock> {
 public:
   static constexpr const char *pyClassName = "BlockSuccessors";
 
@@ -2180,7 +2188,8 @@ class PyBlockSuccessors : public 
Sliceable<PyBlockSuccessors, PyBlock> {
 /// WARNING: This Sliceable is more expensive than the others here because
 /// mlirBlockGetPredecessor actually iterates the use-def chain (of block
 /// operands) anew for each indexed access.
-class PyBlockPredecessors : public Sliceable<PyBlockPredecessors, PyBlock> {
+class MLIR_PYTHON_API_EXPORTED PyBlockPredecessors
+    : public Sliceable<PyBlockPredecessors, PyBlock> {
 public:
   static constexpr const char *pyClassName = "BlockPredecessors";
 
@@ -2218,7 +2227,7 @@ class PyBlockPredecessors : public 
Sliceable<PyBlockPredecessors, PyBlock> {
 
 /// A list of operation attributes. Can be indexed by name, producing
 /// attributes, or by index, producing named attributes.
-class PyOpAttributeMap {
+class MLIR_PYTHON_API_EXPORTED PyOpAttributeMap {
 public:
   PyOpAttributeMap(PyOperationRef operation)
       : operation(std::move(operation)) {}
@@ -2354,7 +2363,7 @@ class PyOpAttributeMap {
   PyOperationRef operation;
 };
 
-MlirValue getUniqueResult(MlirOperation operation);
+MLIR_PYTHON_API_EXPORTED MlirValue getUniqueResult(MlirOperation operation);
 } // namespace python
 } // namespace mlir
 
diff --git a/mlir/include/mlir/Bindings/Python/IRTypes.h 
b/mlir/include/mlir/Bindings/Python/IRTypes.h
index ba9642cf2c6a2..cd0cfbc7d61d8 100644
--- a/mlir/include/mlir/Bindings/Python/IRTypes.h
+++ b/mlir/include/mlir/Bindings/Python/IRTypes.h
@@ -14,7 +14,8 @@
 namespace mlir {
 
 /// Shaped Type Interface - ShapedType
-class PyShapedType : public python::PyConcreteType<PyShapedType> {
+class MLIR_PYTHON_API_EXPORTED PyShapedType
+    : public python::PyConcreteType<PyShapedType> {
 public:
   static const IsAFunctionTy isaFunction;
   static constexpr const char *pyClassName = "ShapedType";

>From d9df23fc7a5a5d84cefa5735eb48893dccc4aff0 Mon Sep 17 00:00:00 2001
From: makslevental <[email protected]>
Date: Tue, 23 Dec 2025 13:37:11 -0800
Subject: [PATCH 2/3] globals doesn't work

---
 mlir/cmake/modules/AddMLIRPython.cmake        | 18 ++++++++++++------
 mlir/examples/standalone/pyproject.toml       |  3 +++
 .../standalone/test/python/smoketest.py       | 19 +++----------------
 mlir/include/mlir/Bindings/Python/Globals.h   |  2 --
 mlir/lib/Bindings/Python/Globals.cpp          | 18 ++++++++++++------
 mlir/test/Examples/standalone/test.wheel.toy  |  7 ++-----
 6 files changed, 32 insertions(+), 35 deletions(-)

diff --git a/mlir/cmake/modules/AddMLIRPython.cmake 
b/mlir/cmake/modules/AddMLIRPython.cmake
index 8ec9304421b54..90b26aad03828 100644
--- a/mlir/cmake/modules/AddMLIRPython.cmake
+++ b/mlir/cmake/modules/AddMLIRPython.cmake
@@ -317,6 +317,10 @@ function(build_nanobind_lib)
   set(NB_LIBRARY_TARGET_NAME 
"nanobind${_ft}-${MLIR_BINDINGS_PYTHON_NB_DOMAIN}")
   set(NB_LIBRARY_TARGET_NAME "${NB_LIBRARY_TARGET_NAME}" PARENT_SCOPE)
   nanobind_build_library(${NB_LIBRARY_TARGET_NAME} AS_SYSINCLUDE)
+  target_compile_definitions(${NB_LIBRARY_TARGET_NAME}
+    PRIVATE
+    NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
+  )
   # nanobind configures with LTO for shared build which doesn't work everywhere
   # (see https://github.com/llvm/llvm-project/issues/139602).
   if(NOT LLVM_ENABLE_LTO)
@@ -365,6 +369,10 @@ function(add_mlir_python_modules name)
     "COMMON_CAPI_LINK_LIBS;DECLARED_SOURCES"
     ${ARGN})
 
+  if(NOT MLIR_BINDINGS_PYTHON_NB_DOMAIN)
+    set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "mlir" CACHE STRING "" FORCE)
+  endif()
+
   # This call sets NB_LIBRARY_TARGET_NAME.
   build_nanobind_lib(
     INSTALL_COMPONENT ${name}
@@ -420,6 +428,8 @@ function(add_mlir_python_modules name)
     get_target_property(_source_type ${sources_target} 
mlir_python_SOURCES_TYPE)
     if(_source_type STREQUAL "support")
       get_target_property(_module_name ${sources_target} 
mlir_python_EXTENSION_MODULE_NAME)
+      # Use a similar mechanism as nanobind to help the runtime loader pick 
the correct lib.
+      set(_module_name "${_module_name}-${MLIR_BINDINGS_PYTHON_NB_DOMAIN}")
       set(_extension_target "${name}.extension.${_module_name}.dso")
       add_mlir_python_extension(${_extension_target} "${_module_name}" 
${NB_LIBRARY_TARGET_NAME}
         INSTALL_COMPONENT ${name}
@@ -844,10 +854,6 @@ function(add_mlir_python_extension libname extname 
nb_library_target_name)
     set(eh_rtti_enable -frtti -fexceptions)
   endif ()
 
-  if(NOT MLIR_BINDINGS_PYTHON_NB_DOMAIN)
-    set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "mlir" CACHE STRING "" FORCE)
-  endif()
-
   if(ARG_SUPPORT_LIB)
     add_library(${libname} SHARED ${ARG_SOURCES})
     if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
@@ -859,9 +865,9 @@ function(add_mlir_python_extension libname extname 
nb_library_target_name)
       NB_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
       MLIR_CAPI_BUILDING_LIBRARY=1
     )
-    if (MSVC)
+    if(MSVC)
       set_property(TARGET ${libname} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)
-    endif ()
+    endif()
   else()
     nanobind_add_module(${libname}
       NB_DOMAIN ${MLIR_BINDINGS_PYTHON_NB_DOMAIN}
diff --git a/mlir/examples/standalone/pyproject.toml 
b/mlir/examples/standalone/pyproject.toml
index c4194153743ef..a90fb417eb426 100644
--- a/mlir/examples/standalone/pyproject.toml
+++ b/mlir/examples/standalone/pyproject.toml
@@ -56,8 +56,11 @@ MLIR_DIR = { env = "MLIR_DIR", default = "" }
 # Non-optional
 CMAKE_BUILD_TYPE = { env = "CMAKE_BUILD_TYPE", default = "Release" }
 MLIR_ENABLE_BINDINGS_PYTHON = "ON"
+
 # Effectively non-optional (any downstream project should specify this).
+MLIR_BINDINGS_PYTHON_NB_DOMAIN = "mlir_standalone"
 MLIR_PYTHON_PACKAGE_PREFIX = "mlir_standalone"
+
 # This specifies the directory in the install directory (i.e., 
/tmp/pip-wheel/platlib) where _mlir_libs, dialects, etc.
 # are installed. Thus, this will be the package location (and the name of the 
package) that pip assumes is
 # the root package.
diff --git a/mlir/examples/standalone/test/python/smoketest.py 
b/mlir/examples/standalone/test/python/smoketest.py
index 9c0ada92551af..ec75790fffeb4 100644
--- a/mlir/examples/standalone/test/python/smoketest.py
+++ b/mlir/examples/standalone/test/python/smoketest.py
@@ -1,20 +1,7 @@
 # RUN: %python %s nanobind | FileCheck %s
 
-from mlir_standalone.ir import *
-from mlir_standalone.dialects import standalone_nanobind as standalone_d
 
-with Context():
-    standalone_d.register_dialects()
-    module = Module.parse(
-        """
-    %0 = arith.constant 2 : i32
-    %1 = standalone.foo %0 : i32
-    """
-    )
-    # CHECK: %[[C:.*]] = arith.constant 2 : i32
-    # CHECK: standalone.foo %[[C]] : i32
-    print(str(module))
 
-    custom_type = standalone_d.CustomType.get("foo")
-    # CHECK: !standalone.custom<"foo">
-    print(custom_type)
+import mlir_standalone.ir
+
+import mlir.ir
diff --git a/mlir/include/mlir/Bindings/Python/Globals.h 
b/mlir/include/mlir/Bindings/Python/Globals.h
index 112c7b9b0547f..d9334cb35cc27 100644
--- a/mlir/include/mlir/Bindings/Python/Globals.h
+++ b/mlir/include/mlir/Bindings/Python/Globals.h
@@ -174,8 +174,6 @@ class MLIR_PYTHON_API_EXPORTED PyGlobals {
   MlirTypeID allocateTypeID() { return typeIDAllocator.allocate(); }
 
 private:
-  static PyGlobals *instance;
-
   nanobind::ft_mutex mutex;
 
   /// Module name prefixes to search under for dialect implementation modules.
diff --git a/mlir/lib/Bindings/Python/Globals.cpp 
b/mlir/lib/Bindings/Python/Globals.cpp
index ecac571a132f6..7e451c8009809 100644
--- a/mlir/lib/Bindings/Python/Globals.cpp
+++ b/mlir/lib/Bindings/Python/Globals.cpp
@@ -19,6 +19,8 @@
 #include "mlir-c/Support.h"
 #include "mlir/Bindings/Python/Nanobind.h"
 
+#include <iostream>
+
 namespace nb = nanobind;
 using namespace mlir;
 
@@ -26,22 +28,26 @@ using namespace mlir;
 // PyGlobals
 // 
-----------------------------------------------------------------------------
 
+namespace {
+python::PyGlobals *pyGlobalsInstance = nullptr;
+}
+
 namespace mlir::python {
-PyGlobals *PyGlobals::instance = nullptr;
 
 PyGlobals::PyGlobals() {
-  assert(!instance && "PyGlobals already constructed");
-  instance = this;
+  std::cerr << MAKE_MLIR_PYTHON_QUALNAME("dialects") << "\n";
+  assert(!pyGlobalsInstance && "PyGlobals already constructed");
+  pyGlobalsInstance = this;
   // The default search path include {mlir.}dialects, where {mlir.} is the
   // package prefix configured at compile time.
   dialectSearchPrefixes.emplace_back(MAKE_MLIR_PYTHON_QUALNAME("dialects"));
 }
 
-PyGlobals::~PyGlobals() { instance = nullptr; }
+PyGlobals::~PyGlobals() { pyGlobalsInstance = nullptr; }
 
 PyGlobals &PyGlobals::get() {
-  assert(instance && "PyGlobals is null");
-  return *instance;
+  assert(pyGlobalsInstance && "PyGlobals is null");
+  return *pyGlobalsInstance;
 }
 
 bool PyGlobals::loadDialectModule(llvm::StringRef dialectNamespace) {
diff --git a/mlir/test/Examples/standalone/test.wheel.toy 
b/mlir/test/Examples/standalone/test.wheel.toy
index c8d188a3cacd0..55847f7430648 100644
--- a/mlir/test/Examples/standalone/test.wheel.toy
+++ b/mlir/test/Examples/standalone/test.wheel.toy
@@ -1,10 +1,6 @@
 # There's no real issue with windows here, it's just that some CMake generated 
paths for targets end up being longer
 # than 255 chars when combined with the fact that pip wants to install into a 
tmp directory buried under
 # C/Users/ContainerAdministrator/AppData/Local/Temp.
-# UNSUPPORTED: target={{.*(windows).*}}
-# REQUIRES: expensive_checks
-# REQUIRES: non-shared-libs-build
-# REQUIRES: bindings-python
 
 # RUN: export CMAKE_BUILD_TYPE=%cmake_build_type
 # RUN: export CMAKE_CXX_COMPILER=%host_cxx
@@ -15,7 +11,8 @@
 # RUN: export LLVM_USE_LINKER=%llvm_use_linker
 # RUN: export MLIR_DIR="%mlir_cmake_dir"
 
-# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w 
"%mlir_obj_root/wheelhouse" -v | tee %t
+# RUN: %python -m pip install scikit-build-core
+# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w 
"%mlir_obj_root/wheelhouse" -v --no-build-isolation | tee %t
 
 # RUN: rm -rf "%mlir_obj_root/standalone-python-bindings-install"
 # RUN: %python -m pip install standalone_python_bindings -f 
"%mlir_obj_root/wheelhouse" --target 
"%mlir_obj_root/standalone-python-bindings-install" -v | tee -a %t

>From b3767af6a16060257b0e7bd4a8772e8b0932e50d Mon Sep 17 00:00:00 2001
From: makslevental <[email protected]>
Date: Tue, 23 Dec 2025 17:00:17 -0800
Subject: [PATCH 3/3] works

---
 .../examples/standalone/python/CMakeLists.txt |   1 +
 .../python/StandaloneExtensionNanobind.cpp    |   6 +-
 .../standalone/test/python/smoketest.py       |  19 ++-
 mlir/include/mlir/Bindings/Python/Globals.h   |   5 +-
 mlir/include/mlir/Bindings/Python/IRCore.h    |  43 ++++--
 mlir/include/mlir/Bindings/Python/IRTypes.h   |   8 +-
 mlir/lib/Bindings/Python/Globals.cpp          |  26 ++--
 mlir/lib/Bindings/Python/IRAffine.cpp         |  34 +++--
 mlir/lib/Bindings/Python/IRAttributes.cpp     |  18 ++-
 mlir/lib/Bindings/Python/IRCore.cpp           |  28 ++--
 mlir/lib/Bindings/Python/IRInterfaces.cpp     |   4 +-
 mlir/lib/Bindings/Python/IRTypes.cpp          |  37 +++--
 mlir/lib/Bindings/Python/MainModule.cpp       | 133 ++++++++++--------
 mlir/lib/Bindings/Python/Pass.cpp             |  39 +++--
 mlir/lib/Bindings/Python/Pass.h               |   3 +-
 mlir/lib/Bindings/Python/Rewrite.cpp          |  43 +++---
 mlir/lib/Bindings/Python/Rewrite.h            |   4 +-
 mlir/python/CMakeLists.txt                    |   1 +
 mlir/test/Examples/standalone/test.wheel.toy  |  14 +-
 .../python/lib/PythonTestModuleNanobind.cpp   |  13 +-
 20 files changed, 300 insertions(+), 179 deletions(-)

diff --git a/mlir/examples/standalone/python/CMakeLists.txt 
b/mlir/examples/standalone/python/CMakeLists.txt
index edaedf18cc843..d3b3aeadb6396 100644
--- a/mlir/examples/standalone/python/CMakeLists.txt
+++ b/mlir/examples/standalone/python/CMakeLists.txt
@@ -3,6 +3,7 @@ include(AddMLIRPython)
 # Specifies that all MLIR packages are co-located under the `mlir_standalone`
 # top level package (the API has been embedded in a relocatable way).
 
add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=${MLIR_PYTHON_PACKAGE_PREFIX}.")
+add_compile_definitions("MLIR_BINDINGS_PYTHON_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}")
 
 
 
################################################################################
diff --git a/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp 
b/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp
index 37737cd89ee1e..c568369913595 100644
--- a/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp
+++ b/mlir/examples/standalone/python/StandaloneExtensionNanobind.cpp
@@ -17,7 +17,8 @@
 
 namespace nb = nanobind;
 
-struct PyCustomType : mlir::python::PyConcreteType<PyCustomType> {
+struct PyCustomType
+    : mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteType<PyCustomType> {
   static constexpr IsAFunctionTy isaFunction = mlirStandaloneTypeIsACustomType;
   static constexpr GetTypeIDFunctionTy getTypeIdFunction =
       mlirStandaloneCustomTypeGetTypeID;
@@ -28,7 +29,8 @@ struct PyCustomType : 
mlir::python::PyConcreteType<PyCustomType> {
     c.def_static(
         "get",
         [](const std::string &value,
-           mlir::python::DefaultingPyMlirContext context) {
+           mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext
+               context) {
           return PyCustomType(
               context->getRef(),
               mlirStandaloneCustomTypeGet(
diff --git a/mlir/examples/standalone/test/python/smoketest.py 
b/mlir/examples/standalone/test/python/smoketest.py
index ec75790fffeb4..4a29e80157f5b 100644
--- a/mlir/examples/standalone/test/python/smoketest.py
+++ b/mlir/examples/standalone/test/python/smoketest.py
@@ -1,7 +1,20 @@
 # RUN: %python %s nanobind | FileCheck %s
+import sys
 
+from mlir_standalone.ir import *
+from mlir_standalone.dialects import standalone_nanobind as standalone_d
 
+with Context():
+    standalone_d.register_dialects()
+    module = Module.parse(
+        """
+    %0 = arith.constant 2 : i32
+    %1 = standalone.foo %0 : i32
+    """
+    )
+    # CHECK: %[[C:.*]] = arith.constant 2 : i32
+    # CHECK: standalone.foo %[[C]] : i32
+    print(str(module))
 
-import mlir_standalone.ir
-
-import mlir.ir
+if sys.argv[1] == "test-upstream":
+    from mlir.ir import *
diff --git a/mlir/include/mlir/Bindings/Python/Globals.h 
b/mlir/include/mlir/Bindings/Python/Globals.h
index d9334cb35cc27..5548a716cbe21 100644
--- a/mlir/include/mlir/Bindings/Python/Globals.h
+++ b/mlir/include/mlir/Bindings/Python/Globals.h
@@ -28,7 +28,7 @@
 
 namespace mlir {
 namespace python {
-
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 /// Globals that are always accessible once the extension has been initialized.
 /// Methods of this class are thread-safe.
 class MLIR_PYTHON_API_EXPORTED PyGlobals {
@@ -174,6 +174,8 @@ class MLIR_PYTHON_API_EXPORTED PyGlobals {
   MlirTypeID allocateTypeID() { return typeIDAllocator.allocate(); }
 
 private:
+  static PyGlobals *instance;
+
   nanobind::ft_mutex mutex;
 
   /// Module name prefixes to search under for dialect implementation modules.
@@ -195,6 +197,7 @@ class MLIR_PYTHON_API_EXPORTED PyGlobals {
   TracebackLoc tracebackLoc;
   TypeIDAllocator typeIDAllocator;
 };
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
 } // namespace python
 } // namespace mlir
 
diff --git a/mlir/include/mlir/Bindings/Python/IRCore.h 
b/mlir/include/mlir/Bindings/Python/IRCore.h
index ceedeb691eb58..7ed0a9f63bfda 100644
--- a/mlir/include/mlir/Bindings/Python/IRCore.h
+++ b/mlir/include/mlir/Bindings/Python/IRCore.h
@@ -33,6 +33,7 @@
 
 namespace mlir {
 namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 class PyBlock;
 class PyDiagnostic;
@@ -325,6 +326,26 @@ class MLIR_PYTHON_API_EXPORTED PyLocation : public 
BaseContextObject {
   MlirLocation loc;
 };
 
+enum PyMlirDiagnosticSeverity : std::underlying_type<
+    MlirDiagnosticSeverity>::type {
+  MlirDiagnosticError = MlirDiagnosticError,
+  MlirDiagnosticWarning = MlirDiagnosticWarning,
+  MlirDiagnosticNote = MlirDiagnosticNote,
+  MlirDiagnosticRemark = MlirDiagnosticRemark
+};
+
+enum PyMlirWalkResult : std::underlying_type<MlirWalkResult>::type {
+  MlirWalkResultAdvance = MlirWalkResultAdvance,
+  MlirWalkResultInterrupt = MlirWalkResultInterrupt,
+  MlirWalkResultSkip = MlirWalkResultSkip
+};
+
+/// Traversal order for operation walk.
+enum PyMlirWalkOrder : std::underlying_type<MlirWalkOrder>::type {
+  MlirWalkPreOrder = MlirWalkPreOrder,
+  MlirWalkPostOrder = MlirWalkPostOrder
+};
+
 /// Python class mirroring the C MlirDiagnostic struct. Note that these structs
 /// are only valid for the duration of a diagnostic callback and attempting
 /// to access them outside of that will raise an exception. This applies to
@@ -334,7 +355,7 @@ class MLIR_PYTHON_API_EXPORTED PyDiagnostic {
   PyDiagnostic(MlirDiagnostic diagnostic) : diagnostic(diagnostic) {}
   void invalidate();
   bool isValid() { return valid; }
-  MlirDiagnosticSeverity getSeverity();
+  PyMlirDiagnosticSeverity getSeverity();
   PyLocation getLocation();
   nanobind::str getMessage();
   nanobind::tuple getNotes();
@@ -342,7 +363,7 @@ class MLIR_PYTHON_API_EXPORTED PyDiagnostic {
   /// Materialized diagnostic information. This is safe to access outside the
   /// diagnostic callback.
   struct DiagnosticInfo {
-    MlirDiagnosticSeverity severity;
+    PyMlirDiagnosticSeverity severity;
     PyLocation location;
     std::string message;
     std::vector<DiagnosticInfo> notes;
@@ -573,8 +594,8 @@ class MLIR_PYTHON_API_EXPORTED PyOperationBase {
                      std::optional<int64_t> bytecodeVersion);
 
   // Implement the walk method.
-  void walk(std::function<MlirWalkResult(MlirOperation)> callback,
-            MlirWalkOrder walkOrder);
+  void walk(std::function<PyMlirWalkResult(MlirOperation)> callback,
+            PyMlirWalkOrder walkOrder);
 
   /// Moves the operation before or after the other operation.
   void moveAfter(PyOperationBase &other);
@@ -2364,6 +2385,7 @@ class MLIR_PYTHON_API_EXPORTED PyOpAttributeMap {
 };
 
 MLIR_PYTHON_API_EXPORTED MlirValue getUniqueResult(MlirOperation operation);
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
 } // namespace python
 } // namespace mlir
 
@@ -2371,11 +2393,16 @@ namespace nanobind {
 namespace detail {
 
 template <>
-struct type_caster<mlir::python::DefaultingPyMlirContext>
-    : MlirDefaultingCaster<mlir::python::DefaultingPyMlirContext> {};
+struct type_caster<
+    mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext>
+    : MlirDefaultingCaster<
+          mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext> {
+};
 template <>
-struct type_caster<mlir::python::DefaultingPyLocation>
-    : MlirDefaultingCaster<mlir::python::DefaultingPyLocation> {};
+struct type_caster<
+    mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyLocation>
+    : MlirDefaultingCaster<
+          mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyLocation> {};
 
 } // namespace detail
 } // namespace nanobind
diff --git a/mlir/include/mlir/Bindings/Python/IRTypes.h 
b/mlir/include/mlir/Bindings/Python/IRTypes.h
index cd0cfbc7d61d8..87e0e10764bd8 100644
--- a/mlir/include/mlir/Bindings/Python/IRTypes.h
+++ b/mlir/include/mlir/Bindings/Python/IRTypes.h
@@ -12,10 +12,11 @@
 #include "mlir/Bindings/Python/NanobindAdaptors.h"
 
 namespace mlir {
-
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 /// Shaped Type Interface - ShapedType
 class MLIR_PYTHON_API_EXPORTED PyShapedType
-    : public python::PyConcreteType<PyShapedType> {
+    : public PyConcreteType<PyShapedType> {
 public:
   static const IsAFunctionTy isaFunction;
   static constexpr const char *pyClassName = "ShapedType";
@@ -26,7 +27,8 @@ class MLIR_PYTHON_API_EXPORTED PyShapedType
 private:
   void requireHasRank();
 };
-
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
 } // namespace mlir
 
 #endif // MLIR_BINDINGS_PYTHON_IRTYPES_H
diff --git a/mlir/lib/Bindings/Python/Globals.cpp 
b/mlir/lib/Bindings/Python/Globals.cpp
index 7e451c8009809..e2e8693ba45f3 100644
--- a/mlir/lib/Bindings/Python/Globals.cpp
+++ b/mlir/lib/Bindings/Python/Globals.cpp
@@ -19,8 +19,6 @@
 #include "mlir-c/Support.h"
 #include "mlir/Bindings/Python/Nanobind.h"
 
-#include <iostream>
-
 namespace nb = nanobind;
 using namespace mlir;
 
@@ -28,26 +26,24 @@ using namespace mlir;
 // PyGlobals
 // 
-----------------------------------------------------------------------------
 
-namespace {
-python::PyGlobals *pyGlobalsInstance = nullptr;
-}
-
-namespace mlir::python {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
+PyGlobals *PyGlobals::instance = nullptr;
 
 PyGlobals::PyGlobals() {
-  std::cerr << MAKE_MLIR_PYTHON_QUALNAME("dialects") << "\n";
-  assert(!pyGlobalsInstance && "PyGlobals already constructed");
-  pyGlobalsInstance = this;
+  assert(!instance && "PyGlobals already constructed");
+  instance = this;
   // The default search path include {mlir.}dialects, where {mlir.} is the
   // package prefix configured at compile time.
   dialectSearchPrefixes.emplace_back(MAKE_MLIR_PYTHON_QUALNAME("dialects"));
 }
 
-PyGlobals::~PyGlobals() { pyGlobalsInstance = nullptr; }
+PyGlobals::~PyGlobals() { instance = nullptr; }
 
 PyGlobals &PyGlobals::get() {
-  assert(pyGlobalsInstance && "PyGlobals is null");
-  return *pyGlobalsInstance;
+  assert(instance && "PyGlobals is null");
+  return *instance;
 }
 
 bool PyGlobals::loadDialectModule(llvm::StringRef dialectNamespace) {
@@ -278,4 +274,6 @@ bool PyGlobals::TracebackLoc::isUserTracebackFilename(
   }
   return isUserTracebackFilenameCache[file];
 }
-} // namespace mlir::python
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
diff --git a/mlir/lib/Bindings/Python/IRAffine.cpp 
b/mlir/lib/Bindings/Python/IRAffine.cpp
index 624d8f0fa57ce..ce235470bbdc7 100644
--- a/mlir/lib/Bindings/Python/IRAffine.cpp
+++ b/mlir/lib/Bindings/Python/IRAffine.cpp
@@ -30,7 +30,7 @@
 
 namespace nb = nanobind;
 using namespace mlir;
-using namespace mlir::python;
+using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN;
 
 using llvm::SmallVector;
 using llvm::StringRef;
@@ -80,7 +80,9 @@ static bool isPermutation(const std::vector<PermutationTy> 
&permutation) {
   return true;
 }
 
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 /// CRTP base class for Python MLIR affine expressions that subclass AffineExpr
 /// and should be castable from it. Intermediate hierarchy classes can be
@@ -358,7 +360,9 @@ class PyAffineCeilDivExpr
   }
 };
 
-} // namespace
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
 
 bool PyAffineExpr::operator==(const PyAffineExpr &other) const {
   return mlirAffineExprEqual(affineExpr, other.affineExpr);
@@ -380,7 +384,9 @@ PyAffineExpr PyAffineExpr::createFromCapsule(const 
nb::object &capsule) {
 
//------------------------------------------------------------------------------
 // PyAffineMap and utilities.
 
//------------------------------------------------------------------------------
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 /// A list of expressions contained in an affine map. Internally these are
 /// stored as a consecutive array leading to inexpensive random access. Both
@@ -416,7 +422,9 @@ class PyAffineMapExprList
 
   PyAffineMap affineMap;
 };
-} // namespace
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
 
 bool PyAffineMap::operator==(const PyAffineMap &other) const {
   return mlirAffineMapEqual(affineMap, other.affineMap);
@@ -438,7 +446,9 @@ PyAffineMap PyAffineMap::createFromCapsule(const nb::object 
&capsule) {
 
//------------------------------------------------------------------------------
 // PyIntegerSet and utilities.
 
//------------------------------------------------------------------------------
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 class PyIntegerSetConstraint {
 public:
@@ -492,7 +502,9 @@ class PyIntegerSetConstraintList
 
   PyIntegerSet set;
 };
-} // namespace
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
 
 bool PyIntegerSet::operator==(const PyIntegerSet &other) const {
   return mlirIntegerSetEqual(integerSet, other.integerSet);
@@ -511,7 +523,9 @@ PyIntegerSet PyIntegerSet::createFromCapsule(const 
nb::object &capsule) {
       rawIntegerSet);
 }
 
-namespace mlir::python {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 void populateIRAffine(nb::module_ &m) {
   
//----------------------------------------------------------------------------
   // Mapping of PyAffineExpr and derived classes.
@@ -998,4 +1012,6 @@ void populateIRAffine(nb::module_ &m) {
   PyIntegerSetConstraint::bind(m);
   PyIntegerSetConstraintList::bind(m);
 }
-} // namespace mlir::python
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
diff --git a/mlir/lib/Bindings/Python/IRAttributes.cpp 
b/mlir/lib/Bindings/Python/IRAttributes.cpp
index e39eabdb136b8..a4d308bf049d8 100644
--- a/mlir/lib/Bindings/Python/IRAttributes.cpp
+++ b/mlir/lib/Bindings/Python/IRAttributes.cpp
@@ -24,7 +24,7 @@
 namespace nb = nanobind;
 using namespace nanobind::literals;
 using namespace mlir;
-using namespace mlir::python;
+using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN;
 
 using llvm::SmallVector;
 
@@ -121,7 +121,9 @@ subsequent processing.
     type or if the buffer does not meet expectations.
 )";
 
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 struct nb_buffer_info {
   void *ptr = nullptr;
@@ -1745,7 +1747,9 @@ nb::object 
symbolRefOrFlatSymbolRefAttributeCaster(PyAttribute &pyAttribute) {
   throw nb::type_error(msg.c_str());
 }
 
-} // namespace
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
 
 void PyStringAttribute::bindDerived(ClassTy &c) {
   c.def_static(
@@ -1791,7 +1795,9 @@ void PyStringAttribute::bindDerived(ClassTy &c) {
       "Returns the value of the string attribute as `bytes`");
 }
 
-namespace mlir::python {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 void populateIRAttributes(nb::module_ &m) {
   PyAffineMapAttribute::bind(m);
   PyDenseBoolArrayAttribute::bind(m);
@@ -1846,4 +1852,6 @@ void populateIRAttributes(nb::module_ &m) {
   PyStridedLayoutAttribute::bind(m);
   registerMLIRError();
 }
-} // namespace mlir::python
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
diff --git a/mlir/lib/Bindings/Python/IRCore.cpp 
b/mlir/lib/Bindings/Python/IRCore.cpp
index fc8743599508d..069e177708afc 100644
--- a/mlir/lib/Bindings/Python/IRCore.cpp
+++ b/mlir/lib/Bindings/Python/IRCore.cpp
@@ -31,13 +31,14 @@
 namespace nb = nanobind;
 using namespace nb::literals;
 using namespace mlir;
-using namespace mlir::python;
 
 using llvm::SmallVector;
 using llvm::StringRef;
 using llvm::Twine;
 
-namespace mlir::python {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
//------------------------------------------------------------------------------
 // PyMlirContext
 
//------------------------------------------------------------------------------
@@ -169,7 +170,8 @@ MlirLogicalResult 
PyMlirContext::ErrorCapture::handler(MlirDiagnostic diag,
   if (self->ctx->emitErrorDiagnostics)
     return mlirLogicalResultFailure();
 
-  if (mlirDiagnosticGetSeverity(diag) != MlirDiagnosticError)
+  if (mlirDiagnosticGetSeverity(diag) !=
+      MlirDiagnosticSeverity::MlirDiagnosticError)
     return mlirLogicalResultFailure();
 
   self->errors.emplace_back(PyDiagnostic(diag).getInfo());
@@ -356,9 +358,10 @@ void PyDiagnostic::checkValid() {
   }
 }
 
-MlirDiagnosticSeverity PyDiagnostic::getSeverity() {
+PyMlirDiagnosticSeverity PyDiagnostic::getSeverity() {
   checkValid();
-  return mlirDiagnosticGetSeverity(diagnostic);
+  return static_cast<PyMlirDiagnosticSeverity>(
+      mlirDiagnosticGetSeverity(diagnostic));
 }
 
 PyLocation PyDiagnostic::getLocation() {
@@ -672,12 +675,12 @@ void PyOperationBase::writeBytecode(const nb::object 
&fileOrStringObject,
 }
 
 void PyOperationBase::walk(
-    std::function<MlirWalkResult(MlirOperation)> callback,
-    MlirWalkOrder walkOrder) {
+    std::function<PyMlirWalkResult(MlirOperation)> callback,
+    PyMlirWalkOrder walkOrder) {
   PyOperation &operation = getOperation();
   operation.checkValid();
   struct UserData {
-    std::function<MlirWalkResult(MlirOperation)> callback;
+    std::function<PyMlirWalkResult(MlirOperation)> callback;
     bool gotException;
     std::string exceptionWhat;
     nb::object exceptionType;
@@ -687,7 +690,7 @@ void PyOperationBase::walk(
                                               void *userData) {
     UserData *calleeUserData = static_cast<UserData *>(userData);
     try {
-      return (calleeUserData->callback)(op);
+      return static_cast<MlirWalkResult>((calleeUserData->callback)(op));
     } catch (nb::python_error &e) {
       calleeUserData->gotException = true;
       calleeUserData->exceptionWhat = std::string(e.what());
@@ -695,7 +698,8 @@ void PyOperationBase::walk(
       return MlirWalkResult::MlirWalkResultInterrupt;
     }
   };
-  mlirOperationWalk(operation, walkCallback, &userData, walkOrder);
+  mlirOperationWalk(operation, walkCallback, &userData,
+                    static_cast<MlirWalkOrder>(walkOrder));
   if (userData.gotException) {
     std::string message("Exception raised in callback: ");
     message.append(userData.exceptionWhat);
@@ -1685,4 +1689,6 @@ void registerMLIRErrorInCore() {
     }
   });
 }
-} // namespace mlir::python
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
diff --git a/mlir/lib/Bindings/Python/IRInterfaces.cpp 
b/mlir/lib/Bindings/Python/IRInterfaces.cpp
index 78d1f977b2ebc..09112d4989ae4 100644
--- a/mlir/lib/Bindings/Python/IRInterfaces.cpp
+++ b/mlir/lib/Bindings/Python/IRInterfaces.cpp
@@ -25,7 +25,7 @@ namespace nb = nanobind;
 
 namespace mlir {
 namespace python {
-
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 constexpr static const char *constructorDoc =
     R"(Creates an interface from a given operation/opview object or from a
 subclass of OpView. Raises ValueError if the operation does not implement the
@@ -469,6 +469,6 @@ void populateIRInterfaces(nb::module_ &m) {
   PyShapedTypeComponents::bind(m);
   PyInferShapedTypeOpInterface::bind(m);
 }
-
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
 } // namespace python
 } // namespace mlir
diff --git a/mlir/lib/Bindings/Python/IRTypes.cpp 
b/mlir/lib/Bindings/Python/IRTypes.cpp
index 7d9a0f16c913a..62fb2ef207d58 100644
--- a/mlir/lib/Bindings/Python/IRTypes.cpp
+++ b/mlir/lib/Bindings/Python/IRTypes.cpp
@@ -20,12 +20,14 @@
 
 namespace nb = nanobind;
 using namespace mlir;
-using namespace mlir::python;
+using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN;
 
 using llvm::SmallVector;
 using llvm::Twine;
 
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 /// Checks whether the given type is an integer or float type.
 static int mlirTypeIsAIntegerOrFloat(MlirType type) {
@@ -508,10 +510,12 @@ class PyComplexType : public 
PyConcreteType<PyComplexType> {
   }
 };
 
-} // namespace
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
 
 // Shaped Type Interface - ShapedType
-void mlir::PyShapedType::bindDerived(ClassTy &c) {
+void PyShapedType::bindDerived(ClassTy &c) {
   c.def_prop_ro(
       "element_type",
       [](PyShapedType &self) -> nb::typed<nb::object, PyType> {
@@ -616,17 +620,18 @@ void mlir::PyShapedType::bindDerived(ClassTy &c) {
       "shaped types.");
 }
 
-void mlir::PyShapedType::requireHasRank() {
+void PyShapedType::requireHasRank() {
   if (!mlirShapedTypeHasRank(*this)) {
     throw nb::value_error(
         "calling this method requires that the type has a rank.");
   }
 }
 
-const mlir::PyShapedType::IsAFunctionTy mlir::PyShapedType::isaFunction =
-    mlirTypeIsAShaped;
+const PyShapedType::IsAFunctionTy PyShapedType::isaFunction = 
mlirTypeIsAShaped;
 
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 /// Vector Type subclass - VectorType.
 class PyVectorType : public PyConcreteType<PyVectorType, PyShapedType> {
@@ -1098,10 +1103,6 @@ class PyFunctionType : public 
PyConcreteType<PyFunctionType> {
   }
 };
 
-static MlirStringRef toMlirStringRef(const std::string &s) {
-  return mlirStringRefCreate(s.data(), s.size());
-}
-
 /// Opaque Type subclass - OpaqueType.
 class PyOpaqueType : public PyConcreteType<PyOpaqueType> {
 public:
@@ -1141,9 +1142,13 @@ class PyOpaqueType : public PyConcreteType<PyOpaqueType> 
{
   }
 };
 
-} // namespace
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
 
-namespace mlir::python {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 void populateIRTypes(nb::module_ &m) {
   PyIntegerType::bind(m);
   PyFloatType::bind(m);
@@ -1177,4 +1182,6 @@ void populateIRTypes(nb::module_ &m) {
   PyOpaqueType::bind(m);
   registerMLIRError();
 }
-} // namespace mlir::python
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
diff --git a/mlir/lib/Bindings/Python/MainModule.cpp 
b/mlir/lib/Bindings/Python/MainModule.cpp
index f72775cc0b83a..392144ec5f0b7 100644
--- a/mlir/lib/Bindings/Python/MainModule.cpp
+++ b/mlir/lib/Bindings/Python/MainModule.cpp
@@ -16,7 +16,7 @@
 namespace nb = nanobind;
 using namespace mlir;
 using namespace nb::literals;
-using namespace mlir::python;
+using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN;
 
 static const char kModuleParseDocstring[] =
     R"(Parses a module's assembly format from a string.
@@ -35,6 +35,56 @@ in `exceptions`. `exceptions` can be either a single 
operation or a list of
 operations.
 )";
 
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
+/// Wrapper for the global LLVM debugging flag.
+struct PyGlobalDebugFlag {
+  static void set(nanobind::object &o, bool enable) {
+    nanobind::ft_lock_guard lock(mutex);
+    mlirEnableGlobalDebug(enable);
+  }
+
+  static bool get(const nanobind::object &) {
+    nanobind::ft_lock_guard lock(mutex);
+    return mlirIsGlobalDebugEnabled();
+  }
+
+  static void bind(nanobind::module_ &m) {
+    // Debug flags.
+    nanobind::class_<PyGlobalDebugFlag>(m, "_GlobalDebug")
+        .def_prop_rw_static("flag", &PyGlobalDebugFlag::get,
+                            &PyGlobalDebugFlag::set, "LLVM-wide debug flag.")
+        .def_static(
+            "set_types",
+            [](const std::string &type) {
+              nanobind::ft_lock_guard lock(mutex);
+              mlirSetGlobalDebugType(type.c_str());
+            },
+            nanobind::arg("types"),
+            "Sets specific debug types to be produced by LLVM.")
+        .def_static(
+            "set_types",
+            [](const std::vector<std::string> &types) {
+              std::vector<const char *> pointers;
+              pointers.reserve(types.size());
+              for (const std::string &str : types)
+                pointers.push_back(str.c_str());
+              nanobind::ft_lock_guard lock(mutex);
+              mlirSetGlobalDebugTypes(pointers.data(), pointers.size());
+            },
+            nanobind::arg("types"),
+            "Sets multiple specific debug types to be produced by LLVM.");
+  }
+
+private:
+  static nanobind::ft_mutex mutex;
+};
+nanobind::ft_mutex PyGlobalDebugFlag::mutex;
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
+
 namespace {
 // see
 // 
https://raw.githubusercontent.com/python/pythoncapi_compat/master/pythoncapi_compat.h
@@ -185,51 +235,6 @@ maybeGetTracebackLocation(const std::optional<PyLocation> 
&location) {
   PyMlirContextRef ref = PyMlirContext::forContext(ctx.get());
   return {ref, mlirLoc};
 }
-
-/// Wrapper for the global LLVM debugging flag.
-struct PyGlobalDebugFlag {
-  static void set(nanobind::object &o, bool enable) {
-    nanobind::ft_lock_guard lock(mutex);
-    mlirEnableGlobalDebug(enable);
-  }
-
-  static bool get(const nanobind::object &) {
-    nanobind::ft_lock_guard lock(mutex);
-    return mlirIsGlobalDebugEnabled();
-  }
-
-  static void bind(nanobind::module_ &m) {
-    // Debug flags.
-    nanobind::class_<PyGlobalDebugFlag>(m, "_GlobalDebug")
-        .def_prop_rw_static("flag", &PyGlobalDebugFlag::get,
-                            &PyGlobalDebugFlag::set, "LLVM-wide debug flag.")
-        .def_static(
-            "set_types",
-            [](const std::string &type) {
-              nanobind::ft_lock_guard lock(mutex);
-              mlirSetGlobalDebugType(type.c_str());
-            },
-            nanobind::arg("types"),
-            "Sets specific debug types to be produced by LLVM.")
-        .def_static(
-            "set_types",
-            [](const std::vector<std::string> &types) {
-              std::vector<const char *> pointers;
-              pointers.reserve(types.size());
-              for (const std::string &str : types)
-                pointers.push_back(str.c_str());
-              nanobind::ft_lock_guard lock(mutex);
-              mlirSetGlobalDebugTypes(pointers.data(), pointers.size());
-            },
-            nanobind::arg("types"),
-            "Sets multiple specific debug types to be produced by LLVM.");
-  }
-
-private:
-  static nanobind::ft_mutex mutex;
-};
-
-nanobind::ft_mutex PyGlobalDebugFlag::mutex;
 } // namespace
 
 
//------------------------------------------------------------------------------
@@ -242,20 +247,20 @@ static void populateIRCore(nb::module_ &m) {
   
//----------------------------------------------------------------------------
   // Enums.
   
//----------------------------------------------------------------------------
-  nb::enum_<MlirDiagnosticSeverity>(m, "DiagnosticSeverity")
-      .value("ERROR", MlirDiagnosticError)
-      .value("WARNING", MlirDiagnosticWarning)
-      .value("NOTE", MlirDiagnosticNote)
-      .value("REMARK", MlirDiagnosticRemark);
+  nb::enum_<PyMlirDiagnosticSeverity>(m, "DiagnosticSeverity")
+      .value("ERROR", PyMlirDiagnosticSeverity::MlirDiagnosticError)
+      .value("WARNING", PyMlirDiagnosticSeverity::MlirDiagnosticWarning)
+      .value("NOTE", PyMlirDiagnosticSeverity::MlirDiagnosticNote)
+      .value("REMARK", PyMlirDiagnosticSeverity::MlirDiagnosticRemark);
 
-  nb::enum_<MlirWalkOrder>(m, "WalkOrder")
-      .value("PRE_ORDER", MlirWalkPreOrder)
-      .value("POST_ORDER", MlirWalkPostOrder);
+  nb::enum_<PyMlirWalkOrder>(m, "WalkOrder")
+      .value("PRE_ORDER", PyMlirWalkOrder::MlirWalkPreOrder)
+      .value("POST_ORDER", PyMlirWalkOrder::MlirWalkPostOrder);
 
-  nb::enum_<MlirWalkResult>(m, "WalkResult")
-      .value("ADVANCE", MlirWalkResultAdvance)
-      .value("INTERRUPT", MlirWalkResultInterrupt)
-      .value("SKIP", MlirWalkResultSkip);
+  nb::enum_<PyMlirWalkResult>(m, "WalkResult")
+      .value("ADVANCE", PyMlirWalkResult::MlirWalkResultAdvance)
+      .value("INTERRUPT", PyMlirWalkResult::MlirWalkResultInterrupt)
+      .value("SKIP", PyMlirWalkResult::MlirWalkResultSkip);
 
   
//----------------------------------------------------------------------------
   // Mapping of Diagnostics.
@@ -1186,7 +1191,7 @@ static void populateIRCore(nb::module_ &m) {
             Note:
               After erasing, any Python references to the operation become 
invalid.)")
       .def("walk", &PyOperationBase::walk, nb::arg("callback"),
-           nb::arg("walk_order") = MlirWalkPostOrder,
+           nb::arg("walk_order") = PyMlirWalkOrder::MlirWalkPostOrder,
            // clang-format off
           nb::sig("def walk(self, callback: Callable[[Operation], WalkResult], 
walk_order: WalkOrder) -> None"),
            // clang-format on
@@ -2305,12 +2310,16 @@ static void populateIRCore(nb::module_ &m) {
   PyAttrBuilderMap::bind(m);
 }
 
-namespace mlir::python {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 void populateIRAffine(nb::module_ &m);
 void populateIRAttributes(nb::module_ &m);
 void populateIRInterfaces(nb::module_ &m);
 void populateIRTypes(nb::module_ &m);
-} // namespace mlir::python
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
 
 // 
-----------------------------------------------------------------------------
 // Module initialization.
@@ -2453,5 +2462,5 @@ NB_MODULE(_mlir, m) {
       m.def_submodule("passmanager", "MLIR Pass Management Bindings");
   populatePassManagerSubmodule(passManagerModule);
   registerMLIRError();
-  registerMLIRErrorInCore();
+  // registerMLIRErrorInCore();
 }
diff --git a/mlir/lib/Bindings/Python/Pass.cpp 
b/mlir/lib/Bindings/Python/Pass.cpp
index 3cfdfe49b4e3e..e35923553e0a1 100644
--- a/mlir/lib/Bindings/Python/Pass.cpp
+++ b/mlir/lib/Bindings/Python/Pass.cpp
@@ -19,9 +19,11 @@
 namespace nb = nanobind;
 using namespace nb::literals;
 using namespace mlir;
-using namespace mlir::python;
+using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN;
 
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 /// Owning Wrapper around a PassManager.
 class PyPassManager {
@@ -53,23 +55,29 @@ class PyPassManager {
   MlirPassManager passManager;
 };
 
-} // namespace
+enum PyMlirPassDisplayMode : std::underlying_type<MlirPassDisplayMode>::type {
+  MLIR_PASS_DISPLAY_MODE_LIST = MLIR_PASS_DISPLAY_MODE_LIST,
+  MLIR_PASS_DISPLAY_MODE_PIPELINE = MLIR_PASS_DISPLAY_MODE_PIPELINE
+};
+
+struct PyMlirExternalPass : MlirExternalPass {};
 
 /// Create the `mlir.passmanager` here.
-void mlir::python::populatePassManagerSubmodule(nb::module_ &m) {
+void populatePassManagerSubmodule(nb::module_ &m) {
   
//----------------------------------------------------------------------------
   // Mapping of enumerated types
   
//----------------------------------------------------------------------------
-  nb::enum_<MlirPassDisplayMode>(m, "PassDisplayMode")
+  nb::enum_<PyMlirPassDisplayMode>(m, "PassDisplayMode")
       .value("LIST", MLIR_PASS_DISPLAY_MODE_LIST)
       .value("PIPELINE", MLIR_PASS_DISPLAY_MODE_PIPELINE);
 
   
//----------------------------------------------------------------------------
   // Mapping of MlirExternalPass
   
//----------------------------------------------------------------------------
-  nb::class_<MlirExternalPass>(m, "ExternalPass")
-      .def("signal_pass_failure",
-           [](MlirExternalPass pass) { mlirExternalPassSignalFailure(pass); });
+  nb::class_<PyMlirExternalPass>(m, "ExternalPass")
+      .def("signal_pass_failure", [](PyMlirExternalPass pass) {
+        mlirExternalPassSignalFailure(pass);
+      });
 
   
//----------------------------------------------------------------------------
   // Mapping of the top-level PassManager
@@ -148,11 +156,12 @@ void 
mlir::python::populatePassManagerSubmodule(nb::module_ &m) {
           "Enable pass timing.")
       .def(
           "enable_statistics",
-          [](PyPassManager &passManager, MlirPassDisplayMode displayMode) {
-            mlirPassManagerEnableStatistics(passManager.get(), displayMode);
+          [](PyPassManager &passManager, PyMlirPassDisplayMode displayMode) {
+            mlirPassManagerEnableStatistics(
+                passManager.get(),
+                static_cast<MlirPassDisplayMode>(displayMode));
           },
-          "displayMode"_a =
-              MlirPassDisplayMode::MLIR_PASS_DISPLAY_MODE_PIPELINE,
+          "displayMode"_a = MLIR_PASS_DISPLAY_MODE_PIPELINE,
           "Enable pass statistics.")
       .def_static(
           "parse",
@@ -211,7 +220,8 @@ void mlir::python::populatePassManagerSubmodule(nb::module_ 
&m) {
             };
             callbacks.run = [](MlirOperation op, MlirExternalPass pass,
                                void *userData) {
-              nb::handle(static_cast<PyObject *>(userData))(op, pass);
+              nb::handle(static_cast<PyObject *>(userData))(
+                  op, PyMlirExternalPass{pass.ptr});
             };
             auto externalPass = mlirCreateExternalPass(
                 passID, mlirStringRefCreate(name->data(), name->length()),
@@ -256,3 +266,6 @@ void mlir::python::populatePassManagerSubmodule(nb::module_ 
&m) {
           "be passed to `parse` for round-tripping.");
   registerMLIRError();
 }
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
diff --git a/mlir/lib/Bindings/Python/Pass.h b/mlir/lib/Bindings/Python/Pass.h
index 0221bd10e723e..1a311666ebecd 100644
--- a/mlir/lib/Bindings/Python/Pass.h
+++ b/mlir/lib/Bindings/Python/Pass.h
@@ -13,8 +13,9 @@
 
 namespace mlir {
 namespace python {
-
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 void populatePassManagerSubmodule(nanobind::module_ &m);
+}
 
 } // namespace python
 } // namespace mlir
diff --git a/mlir/lib/Bindings/Python/Rewrite.cpp 
b/mlir/lib/Bindings/Python/Rewrite.cpp
index 89092b768c6ca..cfe3dd9434e3b 100644
--- a/mlir/lib/Bindings/Python/Rewrite.cpp
+++ b/mlir/lib/Bindings/Python/Rewrite.cpp
@@ -22,9 +22,11 @@
 namespace nb = nanobind;
 using namespace mlir;
 using namespace nb::literals;
-using namespace mlir::python;
+using namespace mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN;
 
-namespace {
+namespace mlir {
+namespace python {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 
 class PyPatternRewriter {
 public:
@@ -60,6 +62,8 @@ class PyPatternRewriter {
   PyMlirContextRef ctx;
 };
 
+struct PyMlirPDLResultList : MlirPDLResultList {};
+
 #if MLIR_ENABLE_PDL_IN_PATTERNMATCH
 static nb::object objectFromPDLValue(MlirPDLValue value) {
   if (MlirValue v = mlirPDLValueAsValue(value); !mlirValueIsNull(v))
@@ -118,7 +122,7 @@ class PyPDLPatternModule {
            void *userData) -> MlirLogicalResult {
           nb::handle f = nb::handle(static_cast<PyObject *>(userData));
           return logicalResultFromObject(
-              f(PyPatternRewriter(rewriter), results,
+              f(PyPatternRewriter(rewriter), PyMlirPDLResultList{results.ptr},
                 objectsFromPDLValues(nValues, values)));
         },
         fn.ptr());
@@ -133,7 +137,7 @@ class PyPDLPatternModule {
            void *userData) -> MlirLogicalResult {
           nb::handle f = nb::handle(static_cast<PyObject *>(userData));
           return logicalResultFromObject(
-              f(PyPatternRewriter(rewriter), results,
+              f(PyPatternRewriter(rewriter), PyMlirPDLResultList{results.ptr},
                 objectsFromPDLValues(nValues, values)));
         },
         fn.ptr());
@@ -223,10 +227,8 @@ class PyRewritePatternSet {
   MlirContext ctx;
 };
 
-} // namespace
-
 /// Create the `mlir.rewrite` here.
-void mlir::python::populateRewriteSubmodule(nb::module_ &m) {
+void populateRewriteSubmodule(nb::module_ &m) {
   
//----------------------------------------------------------------------------
   // Mapping of the PatternRewriter
   
//----------------------------------------------------------------------------
@@ -293,10 +295,10 @@ void mlir::python::populateRewriteSubmodule(nb::module_ 
&m) {
   // Mapping of the PDLResultList and PDLModule
   
//----------------------------------------------------------------------------
 #if MLIR_ENABLE_PDL_IN_PATTERNMATCH
-  nb::class_<MlirPDLResultList>(m, "PDLResultList")
+  nb::class_<PyMlirPDLResultList>(m, "PDLResultList")
       .def(
           "append",
-          [](MlirPDLResultList results, const PyValue &value) {
+          [](PyMlirPDLResultList results, const PyValue &value) {
             mlirPDLResultListPushBackValue(results, value);
           },
           // clang-format off
@@ -305,7 +307,7 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) 
{
           )
       .def(
           "append",
-          [](MlirPDLResultList results, const PyOperation &op) {
+          [](PyMlirPDLResultList results, const PyOperation &op) {
             mlirPDLResultListPushBackOperation(results, op);
           },
           // clang-format off
@@ -314,7 +316,7 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) 
{
           )
       .def(
           "append",
-          [](MlirPDLResultList results, const PyType &type) {
+          [](PyMlirPDLResultList results, const PyType &type) {
             mlirPDLResultListPushBackType(results, type);
           },
           // clang-format off
@@ -323,7 +325,7 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) 
{
           )
       .def(
           "append",
-          [](MlirPDLResultList results, const PyAttribute &attr) {
+          [](PyMlirPDLResultList results, const PyAttribute &attr) {
             mlirPDLResultListPushBackAttribute(results, attr);
           },
           // clang-format off
@@ -333,9 +335,9 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) 
{
   nb::class_<PyPDLPatternModule>(m, "PDLModule")
       .def(
           "__init__",
-          [](PyPDLPatternModule &self, MlirModule module) {
-            new (&self)
-                PyPDLPatternModule(mlirPDLPatternModuleFromModule(module));
+          [](PyPDLPatternModule &self, PyModule &module) {
+            new (&self) PyPDLPatternModule(
+                mlirPDLPatternModuleFromModule(module.get()));
           },
           // clang-format off
           nb::sig("def __init__(self, module: " 
MAKE_MLIR_PYTHON_QUALNAME("ir.Module") ") -> None"),
@@ -394,9 +396,9 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) 
{
        "results.")
       .def(
           "apply_patterns_and_fold_greedily",
-          [](PyModule &module, MlirFrozenRewritePatternSet set) {
+          [](PyModule &module, PyFrozenRewritePatternSet &set) {
             auto status =
-                mlirApplyPatternsAndFoldGreedily(module.get(), set, {});
+                mlirApplyPatternsAndFoldGreedily(module.get(), set.get(), {});
             if (mlirLogicalResultIsFailure(status))
               throw std::runtime_error(
                   "pattern application failed to converge");
@@ -425,9 +427,9 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) 
{
           "results.")
       .def(
           "apply_patterns_and_fold_greedily",
-          [](PyOperationBase &op, MlirFrozenRewritePatternSet set) {
+          [](PyOperationBase &op, PyFrozenRewritePatternSet &set) {
             auto status = mlirApplyPatternsAndFoldGreedilyWithOp(
-                op.getOperation(), set, {});
+                op.getOperation(), set.get(), {});
             if (mlirLogicalResultIsFailure(status))
               throw std::runtime_error(
                   "pattern application failed to converge");
@@ -439,3 +441,6 @@ void mlir::python::populateRewriteSubmodule(nb::module_ &m) 
{
           "Applys the given patterns to the given op greedily while folding "
           "results.");
 }
+} // namespace MLIR_BINDINGS_PYTHON_DOMAIN
+} // namespace python
+} // namespace mlir
diff --git a/mlir/lib/Bindings/Python/Rewrite.h 
b/mlir/lib/Bindings/Python/Rewrite.h
index f8ffdc7bdc458..d287f19187708 100644
--- a/mlir/lib/Bindings/Python/Rewrite.h
+++ b/mlir/lib/Bindings/Python/Rewrite.h
@@ -13,9 +13,9 @@
 
 namespace mlir {
 namespace python {
-
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
 void populateRewriteSubmodule(nanobind::module_ &m);
-
+}
 } // namespace python
 } // namespace mlir
 
diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt
index b22d2ec75b3ba..2d2ae26bf3b28 100644
--- a/mlir/python/CMakeLists.txt
+++ b/mlir/python/CMakeLists.txt
@@ -3,6 +3,7 @@ include(AddMLIRPython)
 # Specifies that all MLIR packages are co-located under the 
`MLIR_PYTHON_PACKAGE_PREFIX.`
 # top level package (the API has been embedded in a relocatable way).
 
add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=${MLIR_PYTHON_PACKAGE_PREFIX}.")
+add_compile_definitions("MLIR_BINDINGS_PYTHON_DOMAIN=${MLIR_BINDINGS_PYTHON_NB_DOMAIN}")
 set(MLIRPythonModules_ROOT_PREFIX 
"${MLIR_BINARY_DIR}/${MLIR_BINDINGS_PYTHON_INSTALL_PREFIX}")
 set(PYTHON_SOURCE_DIR "${MLIR_SOURCE_DIR}/lib/Bindings/Python")
 
diff --git a/mlir/test/Examples/standalone/test.wheel.toy 
b/mlir/test/Examples/standalone/test.wheel.toy
index 55847f7430648..91fed38e28612 100644
--- a/mlir/test/Examples/standalone/test.wheel.toy
+++ b/mlir/test/Examples/standalone/test.wheel.toy
@@ -1,6 +1,10 @@
 # There's no real issue with windows here, it's just that some CMake generated 
paths for targets end up being longer
 # than 255 chars when combined with the fact that pip wants to install into a 
tmp directory buried under
 # C/Users/ContainerAdministrator/AppData/Local/Temp.
+# UNSUPPORTED: target={{.*(windows).*}}
+# REQUIRES: expensive_checks
+# REQUIRES: non-shared-libs-build
+# REQUIRES: bindings-python
 
 # RUN: export CMAKE_BUILD_TYPE=%cmake_build_type
 # RUN: export CMAKE_CXX_COMPILER=%host_cxx
@@ -11,21 +15,21 @@
 # RUN: export LLVM_USE_LINKER=%llvm_use_linker
 # RUN: export MLIR_DIR="%mlir_cmake_dir"
 
-# RUN: %python -m pip install scikit-build-core
-# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w 
"%mlir_obj_root/wheelhouse" -v --no-build-isolation | tee %t
+# RUN: %python -m pip wheel "%mlir_src_root/examples/standalone" -w 
"%mlir_obj_root/wheelhouse" -v | tee %t
 
 # RUN: rm -rf "%mlir_obj_root/standalone-python-bindings-install"
 # RUN: %python -m pip install standalone_python_bindings -f 
"%mlir_obj_root/wheelhouse" --target 
"%mlir_obj_root/standalone-python-bindings-install" -v | tee -a %t
 
-# RUN: export PYTHONPATH="%mlir_obj_root/standalone-python-bindings-install"
-# RUN: %python "%mlir_src_root/examples/standalone/test/python/smoketest.py" 
nanobind | tee -a %t
+# RUN: export 
PYTHONPATH="%mlir_obj_root/standalone-python-bindings-install:%mlir_obj_root/python_packages/mlir_core"
+# RUN: %python "%mlir_src_root/examples/standalone/test/python/smoketest.py" 
test-upstream 2>&1 | tee -a %t
 
 # RUN: FileCheck --input-file=%t %s
 
 # CHECK: Successfully built standalone-python-bindings
 
+# CHECK-NOT: RuntimeWarning: nanobind: type '{{.*}}' was already registered!
+
 # CHECK: module {
 # CHECK:   %[[C2:.*]] = arith.constant 2 : i32
 # CHECK:   %[[V0:.*]] = standalone.foo %[[C2]] : i32
 # CHECK: }
-
diff --git a/mlir/test/python/lib/PythonTestModuleNanobind.cpp 
b/mlir/test/python/lib/PythonTestModuleNanobind.cpp
index c8b95e2316778..43573cbc305fa 100644
--- a/mlir/test/python/lib/PythonTestModuleNanobind.cpp
+++ b/mlir/test/python/lib/PythonTestModuleNanobind.cpp
@@ -27,7 +27,8 @@ static bool mlirTypeIsARankedIntegerTensor(MlirType t) {
          mlirTypeIsAInteger(mlirShapedTypeGetElementType(t));
 }
 
-struct PyTestType : mlir::python::PyConcreteType<PyTestType> {
+struct PyTestType
+    : mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteType<PyTestType> {
   static constexpr IsAFunctionTy isaFunction = mlirTypeIsAPythonTestTestType;
   static constexpr GetTypeIDFunctionTy getTypeIdFunction =
       mlirPythonTestTestTypeGetTypeID;
@@ -37,7 +38,8 @@ struct PyTestType : mlir::python::PyConcreteType<PyTestType> {
   static void bindDerived(ClassTy &c) {
     c.def_static(
         "get",
-        [](mlir::python::DefaultingPyMlirContext context) {
+        [](mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext
+               context) {
           return PyTestType(context->getRef(),
                             mlirPythonTestTestTypeGet(context.get()->get()));
         },
@@ -45,7 +47,9 @@ struct PyTestType : mlir::python::PyConcreteType<PyTestType> {
   }
 };
 
-class PyTestAttr : public mlir::python::PyConcreteAttribute<PyTestAttr> {
+class PyTestAttr
+    : public mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::PyConcreteAttribute<
+          PyTestAttr> {
 public:
   static constexpr IsAFunctionTy isaFunction =
       mlirAttributeIsAPythonTestTestAttribute;
@@ -57,7 +61,8 @@ class PyTestAttr : public 
mlir::python::PyConcreteAttribute<PyTestAttr> {
   static void bindDerived(ClassTy &c) {
     c.def_static(
         "get",
-        [](mlir::python::DefaultingPyMlirContext context) {
+        [](mlir::python::MLIR_BINDINGS_PYTHON_DOMAIN::DefaultingPyMlirContext
+               context) {
           return PyTestAttr(context->getRef(), mlirPythonTestTestAttributeGet(
                                                    context.get()->get()));
         },

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to