code: def test_HasProps_equals() -> None:
      class Foo(HasProps):
          x = Int(12)
          y = String("hello")
          z = List(Int, default=[1, 2, 3])
  
      class FooUnrelated(HasProps):
          x = Int(12)
          y = String("hello")
          z = List(Int, default=[1, 2, 3])
  
      v = Foo().equals(Foo())
      assert v is True
  
      v = Foo(x=1).equals(Foo(x=1))
      assert v is True
  
      v = Foo(x=1).equals(Foo(x=2))
      assert v is False
  
      v = Foo(x=1).equals(1)
      assert v is False
  
      v = Foo().equals(FooUnrelated())
      assert v is False
  
imports: from __future__ import annotations
  import pytest
  import numpy
  from bokeh.core.has_props import HasProps, Local
  from bokeh.core.properties import Alias, Dict, Enum, Float, Instance, Int, List, NotSerialized, Nullable, NumberSpec, Override, Readonly, String, UnsetValueError
  from bokeh.model import Model
  from tests.support.util.api import verify_all
  import bokeh.core.properties
label_desc: Use image node_id 1 for calling a global function with example usage: test_HasProps_equals() without return types