<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def gen_postinit(self, cls: ClassDefinition, slotname: str) -> Optional[str]: """ Generate python post init rules for slot in class """

        rlines: List[str] = []
        slot = self.schema.slots[slotname]
        if slot.alias:
            slotname = slot.alias
        slotname = self.python_name_for(slotname)
        range_type_name = self.range_type_name(slot, cls.name)

        # Generate existence check for required slots.  Note that inherited classes have to check post-init because
        # named variables can't be mixed in the class signature
        if slot.primary_key or slot.identifier or slot.required:
            if cls.is_a:
                rlines.append(f'if self.{slotname} is None:')
                rlines.append(f'\traise ValueError(f"{slotname} must be supplied")')
                rlines.append(f'if not isinstance(self.{slotname}, {range_type_name}):')
                rlines.append(f'\tself.{slotname} = {range_type_name}(self.{slotname})')
        elif slot.range in self.schema.classes or slot.range in self.schema.types:
            if not slot.multivalued:
                rlines.append(f'if self.{slotname} and not isinstance(self.{slotname}, {range_type_name}):')
                # Another really wierd case -- a class that has no properties
                if slot.range in self.schema.classes and not self.all_slots_for(self.schema.classes[slot.range]):
                    rlines.append(f'\tself.{slotname} = {range_type_name}()')
                else:
                    rlines.append(f'\tself.{slotname} = {range_type_name}(self.{slotname})')
            elif slot.inlined:
                slot_range_cls = self.schema.classes[slot.range]
                pkeys = self.primary_keys_for(slot_range_cls)
                if pkeys:
                    # Special situation -- if there are only two values: primary key and value,
                    # we load it is a list, not a dictionary
                    if len(self.all_slots_for(slot_range_cls)) - len(pkeys) == 1:
                        class_init = '(k, v)'
                    else:
                        pkey_name = self.python_name_for(pkeys[0])
                        class_init = f'({pkey_name}=k, **({{}} if v is None else v))'
                    rlines.append(f'for k, v in self.{slotname}.items():')
                    rlines.append(f'\tif not isinstance(v, {range_type_name}):')
                    rlines.append(f'\t\tself.{slotname}[k] = {range_type_name}{class_init}')
            else:
                rlines.append(f'self.{slotname} = [v if isinstance(v, {range_type_name})')
                indent = len(f'self.{slotname} = [') * ' '
                rlines.append(f'{indent}else {range_type_name}(v) for v in self.{slotname}]')
        return '\n\t\t'.join(rlines)