def clazz(clazz, parent_clazz, description, link, params_string, init_super_args=None):
    """
    Live template for pycharm:

    y = clazz(clazz="$clazz$", parent_clazz="%parent$", description="$desc$", link="$lnk$", params_string="$first_param$")
    """
    init_description_w_tabs  = description.strip().replace("\n", "\n\t\t")
    clazz_description_w_tabs = description.strip().replace("\n", "\n\t")
    imports = [[], []]
    args = []
    args2 = []
    kwargs = []
    kwargs2 = []
    asserts = []
    str_args = ""
    str_kwargs = ""
    to_array1 = []
    to_array2 = []
    from_array1 = []
    from_array2 = []
    param_strings = params_string.split("\n")
    for param in param_strings:
        assert_commands, assert_comments, param_name, param_type, table, non_buildin_type, param_name_input = parse_param_types(param)
        param_description = table[2].strip()
        param_needed = not param_description.startswith("Optional.")
        asserts.append("")
        if param_needed:
            args.append(param_name)
            str_args += '\n\n\t\t:param {key}: {descr}\n\t\t:type  {key}: {type}'.format(key=param_name, descr=param_description, type=get_type_path(param_type))
            if assert_commands:
                asserts.append("assert({var} is not None)".format(var=param_name))
                asserts.append("assert({ass})".format(ass=" or ".join(assert_commands)) + (("  # {comment}".format(comment=", ".join(assert_comments))) if assert_comments else ""))
            if non_buildin_type:
                to_array1.append('array["{var}"] = self.{var}.to_array()'.format(var=param_name))
                from_array1.append("data['{var}'] = {type}.from_array(array.get('{array_key}'))".format(var=param_name, array_key=param_name_input, type=non_buildin_type))
            else:
                to_array1.append('array["{var}"] = self.{var}'.format(var=param_name))
                from_array2.append("data['{var}'] = array.get('{array_key}')  # type {type}".format(var=param_name, array_key=param_name_input, type=non_buildin_type))
            # end if non_buildin_type
        else:
            kwargs.append("{param_name}=None".format(param_name=param_name))
            str_kwargs += '\n\n\t\t:keyword {key}: {descr}\n\t\t:type    {key}: {type}'.format(key=param_name, descr=param_description, type=param_type)
            if assert_commands:
                asserts.append("assert({var} is None or {ass})".format(var=param_name, ass=" or ".join(assert_commands)) + (("  # {comment}".format(comment=", ".join(assert_comments))) if assert_comments else ""))
            to_array2.append('if self.{var} is not None:'.format(var=param_name))
            if non_buildin_type:
                to_array2.append('\tarray["{var}"] = self.{var}.to_array()'.format(var=param_name))
                from_array2.append("data['{var}'] = {type}.from_array(array.get('{array_key}'))".format(var=param_name, array_key=param_name_input, type=non_buildin_type))
            else:
                to_array2.append('\tarray["{var}"] = self.{var}'.format(var=param_name))
                from_array2.append("data['{var}'] = array.get('{array_key}')  # type {type}".format(var=param_name, array_key=param_name_input, type=non_buildin_type))
        # end if non_buildin_type
        asserts.append("self.{param_name} = {param_name}".format(param_name=param_name))
    param_description = ""
    if len(str_args)>0:
        param_description += '\n\t\tParameters:'
        param_description += str_args
    if len(str_kwargs)>0:
        param_description += '\n\n\n\t\tOptional keyword parameters:'
        param_description += str_kwargs
    args.extend(kwargs)
    to_array = ["array = super({clazz}, self).to_array()".format(clazz=clazz)]
    to_array.extend(to_array1)
    to_array.extend(to_array2)
    from_array = ["data = super({clazz}).from_array(array)".format(clazz=clazz)]
    from_array.extend(from_array1)
    from_array.extend(from_array2)
    from_array.append("return {clazz}(**data)".format(clazz=clazz))
    result = 'class {clazz}({parent_clazz}):\n' \
             '\t"""\n' \
             '\t{clazz_description_w_tabs}\n' \
             '\n' \
             '\t{link}\n' \
             '\t"""\n' \
             '\tdef __init__(self, {params}):\n' \
             '\t\t"""\n' \
             '\t\t{init_description_w_tabs}\n' \
             '\n' \
             '\t\t{link}\n' \
             '\n' \
             '{param_description}\n' \
             '\t\t"""\n' \
             '\t\tsuper({clazz}, self).__init__({init_super_args})\n' \
             '\t\t{asserts_with_tabs}\n' \
             '\t# end def __init__\n' \
             '\n' \
             '\tdef to_array(self):\n' \
             '\t\t{to_array_with_tabs}\n' \
             '\t\treturn array\n' \
             '\t# end def to_array\n' \
             '\n' \
             '\t@staticmethod\n' \
             '\tdef from_array(array):\n' \
             '\t\tif array is None:\n' \
             '\t\t\treturn None\n' \
             '\t\t# end if\n' \
             '\t\t{from_array_with_tabs}\n' \
             '\t# end def from_array\n' \
             '# end class {clazz}\n'.format(
        clazz=clazz, parent_clazz=parent_clazz, params=", ".join(args), param_description = param_description,
        clazz_description_w_tabs=clazz_description_w_tabs, init_description_w_tabs=init_description_w_tabs, link=link,
        asserts_with_tabs="\n\t\t".join(asserts), to_array_with_tabs="\n\t\t".join(to_array),
        from_array_with_tabs="\n\t\t".join(from_array),
        init_super_args=(", ".join(init_super_args) if init_super_args else "")
    )
    result = result.replace("\t", "    ")
    return result
Live template for pycharm:

    y = clazz(clazz="$clazz$", parent_clazz="%parent$", description="$desc$", link="$lnk$", params_string="$first_param$")