<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def frames( self, *, callers: Optional[Union[str, List[str]]] = None, callees: Optional[Union[str, List[str]]] = None, kind: Optional[TraceKind] = None, limit: Optional[int] = 10, ):
 """Display trace frames independent of the current issue. Parameters (all optional):
 callers: str or list[str] filter traces by this caller name callees: str or list[str] filter traces by this callee name kind: precondition|postcondition the type of trace frames to show limit: int (default: 10) how many trace frames to display (specify limit=None for all) Sample usage: frames callers="module.function", kind=postcondition String filters support LIKE wildcards (%, _) from SQL: % matches anything (like .* in regex) _ matches 1 character (like . in regex) """

        with self.db.make_session() as session:
            query = (
                session.query(
                    TraceFrame.id,
                    CallerText.contents.label("caller"),
                    TraceFrame.caller_port,
                    CalleeText.contents.label("callee"),
                    TraceFrame.callee_port,
                )
                .filter(TraceFrame.run_id == self.current_run_id)
                .join(CallerText, CallerText.id == TraceFrame.caller_id)
                .join(CalleeText, CalleeText.id == TraceFrame.callee_id)
            )

            if callers is not None:
                query = self._add_list_or_string_filter_to_query(
                    callers, query, CallerText.contents, "callers"
                )

            if callees is not None:
                query = self._add_list_or_string_filter_to_query(
                    callees, query, CalleeText.contents, "callees"
                )

            if kind is not None:
                if kind not in {TraceKind.PRECONDITION, TraceKind.POSTCONDITION}:
                    raise UserError(
                        "Try 'frames kind=postcondition'"
                        " or 'frames kind=precondition'."
                    )
                query = query.filter(TraceFrame.kind == kind)

            if limit is not None and not isinstance(limit, int):
                raise UserError("'limit' should be an int or None.")

            trace_frames = query.group_by(TraceFrame.id).order_by(
                CallerText.contents, CalleeText.contents
            )

            total_trace_frames = trace_frames.count()
            limit = limit or total_trace_frames

            self._output_trace_frames(
                self._group_trace_frames(trace_frames, limit), limit, total_trace_frames
            )