```ruby
module PyCall
  module PyObjectWrapper
    def initialize(pyobj, pytype=nil)
      check_type pyobj, pytype
      pytype ||= LibPython.PyObject_Type(pyobj)
      @__pyobj__ = pyobj
    end

    attr_reader :__pyobj__

    def ==(other)
      case other
      when self.class
        __pyobj__ == other.__pyobj__
      when PyObject
        __pyobj__ == other
      else
        super
      end
    end

    def call(*args, **kwargs)
      __pyobj__.call(*args, **kwargs)
    end

    def method_missing(name, *args, **kwargs)
      if PyCall.hasattr?(__pyobj__, name.to_s)
        PyCall.getattr(__pyobj__, name)
      else
        super
      end
    end

    def to_s
      __pyobj__.to_s
    end

    def inspect
      __pyobj__.inspect
    end

    private

    def check_type(pyobj, pytype)
      return if pyobj.kind_of?(PyObject)
      return if pytype.nil? || pyobj.kind_of?(pytype)
      raise TypeError, "the argument must be a PyObject of #{pytype}"
    end
  end
end
```

Add wrap_class class method or a subclass of PyObjectWrapper
user
```ruby
module PyCall
  module PyObjectWrapper
    module ClassMethods
      private

      def wrap_class(pyobj)
        define_singleton_method(:__pyobj__) { pyobj }

        PyCall.dir(__pyobj__).each do |name|
          obj = PyCall.getattr(__pyobj__, name)
          next unless obj.kind_of?(PyCall::PyObject) || obj.kind_of?(PyCall::PyObjectWrapper)
          next unless PyCall.callable?(obj)

          define_method(name) do |*args, **kwargs|
            PyCall.getattr(__pyobj__, name).(*args, **kwargs)
          end
        end

        class << self
          def method_missing(name, *args, **kwargs)
            return super unless PyCall.hasattr?(__pyobj__, name)
            PyCall.getattr(__pyobj__, name)
          end
        end

        PyCall::Conversions.python_type_mapping(__pyobj__, self)
      end
    end

    def self.included(mod)
      mod.extend ClassMethods
    end

    def initialize(pyobj, pytype=nil)
      check_type pyobj, pytype
      pytype ||= LibPython.PyObject_Type(pyobj)
      @__pyobj__ = pyobj
    end

    attr_reader :__pyobj__

    def ==(other)
      case other
      when self.class
        __pyobj__ == other.__pyobj__
      when PyObject
        __pyobj__ == other
      else
        super
      end
    end

    def call(*args, **kwargs)
      __pyobj__.call(*args, **kwargs)
    end

    def method_missing(name, *args, **kwargs)
      if PyCall.hasattr?(__pyobj__, name.to_s)
        PyCall.getattr(__pyobj__, name)
      else
        super
      end
    end

    def to_s
      __pyobj__.to_s
    end

    def inspect
      __pyobj__.inspect
    end

    private

    def check_type(pyobj, pytype)
      return if pyobj.kind_of?(PyObject)
      return if pytype.nil? || pyobj.kind_of?(pytype)
      raise TypeError, "the argument must be a PyObject of #{pytype}"
    end
  end
end
```
assistant