docstr: Builds a property
  
  Parameters
  ----------
  class_name : `str`
      Name of the class
  
  attrs : `dict`
      The attributes of the class
  
  attr_name : `str`
      Name of the attribute for which we build a property
  
  writable : `bool`
      If True, we attribute can be changed by the user. If not,
      then an error will be raise when trying to change it.
  
  override : `bool`
      Not implemented yet
  
  cpp_setter : `str` or `None`
      Name of the setter in the c++ object embedded in the class
      for the attribute
  
  Returns
  -------
  output : property
      The required property
docstr_tok: ["Builds","a","property","Parameters","--","--","--","--","--","class_name",":","`","str","`","Name","of","the","class","attrs",":","`","dict","`","The","attributes","of","the","class","attr_name",":","`","str","`","Name","of","the","attribute","for","which","we","build","a","property","writable",":","`","bool","`","If","True",",","we","attribute","can","be","changed","by","the","user",".","If","not",",","then","an","error","will","be","raise","when","trying","to","change","it",".","override",":","`","bool","`","Not","implemented","yet","cpp_setter",":","`","str","`","or","`","None","`","Name","of","the","setter","in","the","c++","object","embedded","in","the","class","for","the","attribute","Returns","--","--","--","-","output",":","property","The","required","property"]
code: def build_property(
      class_name, attrs, attr_name, writable, cpp_setter
  ):
      """
      Builds a property
  
      Parameters
      ----------
      class_name : `str`
          Name of the class
  
      attrs : `dict`
          The attributes of the class
  
      attr_name : `str`
          Name of the attribute for which we build a property
  
      writable : `bool`
          If True, we attribute can be changed by the user. If not,
          then an error will be raise when trying to change it.
  
      override : `bool`
          Not implemented yet
  
      cpp_setter : `str` or `None`
          Name of the setter in the c++ object embedded in the class
          for the attribute
  
      Returns
      -------
      output : property
          The required property
      """
  
      hidden_name = BaseMeta.hidden_attr(attr_name)
  
      def getter(self):
          # if it was not assigned yet we raise the correct error message
          if not hasattr(self, hidden_name):
              raise AttributeError(
                  "'%s' object has no attribute '%s'"
                  % (class_name, attr_name)
              )
          # Get the attribute
          return object.__getattribute__(self, hidden_name)
  
      def create_base_setter():
          if cpp_setter is None:
              # There is no C++ setter, we just set the attribute
              def setter(self, val):
                  object.__setattr__(self, hidden_name, val)
  
          else:
              # There is a C++ setter to apply
              def setter(self, val):
                  object.__setattr__(self, hidden_name, val)
                  # We update the C++ object embedded in the class
                  # as well.
                  BaseMeta.set_cpp_attribute(self, val, cpp_setter)
  
          return setter
  
      base_setter = create_base_setter()
      if writable:
          setter = base_setter
      else:
          # If it is not writable we wrap the base setter with something
          # that detect if attribute setting was called in __init__
          def setter(self, val):
              set_in_init = Base.detect_if_called_in_init(self)
              # If and only if this was launched from our instance's __init__
              # we allow user to set the attribute
              if set_in_init:
                  base_setter(self, val)
              else:
                  raise AttributeError(
                      "%s is readonly in %s"
                      % (str(attr_name), class_name)
                  )
  
      def deletter(self):
          raise AttributeError(
              "can't delete %s in %s" % (str(attr_name), class_name)
          )
  
      # We set doc to None otherwise it will interfere with
      # the docstring of the class.
      # This is very useful as we can have bugs with sphinx
      # otherwise (conflict between an attribute's docstring
      # and a docstring of a property with the same name).
      # All attributes are actually properties when the base
      # class is Base.
      # The docstring of all properties are then putted back
      # in the __init__ of the Base class below.
      prop = property(getter, setter, deletter, None)
      return prop
  
imports: import os
  import inspect
  from datetime import datetime
  from abc import ABCMeta
  import json
  import pydoc
  import numpy
  import numpydoc
  from numpydoc import docscrape
  import copy
label_desc: Use image node_id 4 for calling the BaseMeta obj's underlying member method code with example usage: obj.build_property(class_name, attrs, attr_name, writable, cpp_setter) and returns: prop, object, setter