code: def test_HasProps_clone() -> None:
      class CloneModel(HasProps):
          p0 = Int()
          p1 = Alias("p0")
          p2 = List(Int)
          p3 = Readonly(
              Nullable(Instance(lambda: CloneModel)), default=None
          )
  
      obj0 = CloneModel(
          p0=10, p2=[1, 2, 3], p3=CloneModel(p0=20, p2=[4, 5, 6])
      )
      props0 = obj0.properties_with_values(include_defaults=False)
  
      obj1 = obj0.clone()
      props1 = obj1.properties_with_values(include_defaults=False)
      assert props0 == props1
  
      assert obj1.p0 == obj0.p0
      assert obj1.p1 == obj0.p1
      assert obj1.p2 == obj0.p2
      assert obj1.p3 == obj0.p3
  
      obj1.p0 = 20
      assert obj1.p0 == obj1.p1 == 20
      assert obj0.p0 == obj0.p1 == 10
  
      obj1.p2.append(4)
      assert obj1.p2 == [1, 2, 3, 4]
      assert obj0.p2 == [1, 2, 3, 4]
  
      obj1.p2 = [10, 20]
      assert obj1.p2 == [10, 20]
      assert obj0.p2 == [1, 2, 3, 4]
  
      obj1.p3.p0 = 30
      assert obj1.p3.p0 == 30
      assert obj0.p3.p0 == 30
  
      with pytest.raises(
          RuntimeError, match="CloneModel.p3 is a readonly property"
      ):
          obj0.p3 = None
      with pytest.raises(
          RuntimeError, match="CloneModel.p3 is a readonly property"
      ):
          obj1.p3 = None
  
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 2 for calling a global function with example usage: test_HasProps_clone() without return types