| """ |
| Simple utility for splitting user input. This is used by both inputsplitter and |
| prefilter. |
| """ |
|
|
| |
| |
| |
|
|
| import re |
| import sys |
| import warnings |
|
|
| from IPython.core.oinspect import OInfo |
|
|
| |
| |
| |
|
|
| |
| |
|
|
| |
| |
|
|
| |
| |
| |
| |
|
|
| line_split = re.compile( |
| r""" |
| ^(\s*) # any leading space |
| ([,;/%]|!!?|\?\??)? # escape character or characters |
| \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading % |
| # to correctly treat things like '?%magic' |
| (.*?$|$) # rest of line |
| """, |
| re.VERBOSE, |
| ) |
|
|
|
|
| def split_user_input( |
| line: str, pattern: re.Pattern[str] | None = None |
| ) -> tuple[str, str, str, str]: |
| """Split user input into initial whitespace, escape character, function part |
| and the rest. |
| """ |
| assert isinstance(line, str) |
|
|
| if pattern is None: |
| pattern = line_split |
| match = pattern.match(line) |
| if not match: |
| |
| try: |
| ifun, the_rest = line.split(None, 1) |
| except ValueError: |
| |
| ifun, the_rest = line, "" |
| pre = re.match(r"^(\s*)(.*)", line).groups()[0] |
| esc = "" |
| else: |
| pre, esc, ifun, the_rest = match.groups() |
|
|
| |
| |
| return pre, esc or "", ifun.strip(), the_rest |
|
|
|
|
| class LineInfo: |
| """A single line of input and associated info. |
| |
| Includes the following as properties: |
| |
| line |
| The original, raw line |
| |
| continue_prompt |
| Is this line a continuation in a sequence of multiline input? |
| |
| pre |
| Any leading whitespace. |
| |
| esc |
| The escape character(s) in pre or the empty string if there isn't one. |
| Note that '!!' and '??' are possible values for esc. Otherwise it will |
| always be a single character. |
| |
| ifun |
| The 'function part', which is basically the maximal initial sequence |
| of valid python identifiers and the '.' character. This is what is |
| checked for alias and magic transformations, used for auto-calling, |
| etc. In contrast to Python identifiers, it may start with "%" and contain |
| "*". |
| |
| the_rest |
| Everything else on the line. |
| |
| raw_the_rest |
| the_rest without whitespace stripped. |
| """ |
|
|
| line: str |
| continue_prompt: bool |
| pre: str |
| esc: str |
| ifun: str |
| raw_the_rest: str |
| the_rest: str |
| pre_char: str |
| pre_whitespace: str |
|
|
| def __init__(self, line: str, continue_prompt: bool = False) -> None: |
| assert isinstance(line, str) |
| self.line = line |
| self.continue_prompt = continue_prompt |
| self.pre, self.esc, self.ifun, self.raw_the_rest = split_user_input(line) |
| self.the_rest = self.raw_the_rest.lstrip() |
|
|
| self.pre_char = self.pre.strip() |
| if self.pre_char: |
| self.pre_whitespace = "" |
| else: |
| self.pre_whitespace = self.pre |
|
|
| def ofind(self, ip) -> OInfo: |
| """Do a full, attribute-walking lookup of the ifun in the various |
| namespaces for the given IPython InteractiveShell instance. |
| |
| Return a dict with keys: {found, obj, ospace, ismagic} |
| |
| Note: can cause state changes because of calling getattr, but should |
| only be run if autocall is on and if the line hasn't matched any |
| other, less dangerous handlers. |
| |
| Does cache the results of the call, so can be called multiple times |
| without worrying about *further* damaging state. |
| |
| .. deprecated:: 9.8 |
| Use ``shell._ofind(line_info.ifun)`` directly instead. |
| """ |
| warnings.warn( |
| "LineInfo.ofind() is deprecated since IPython 9.9. " |
| "Use shell._ofind(line_info.ifun) directly instead.", |
| DeprecationWarning, |
| stacklevel=2, |
| ) |
| return ip._ofind(self.ifun) |
|
|
| def __str__(self) -> str: |
| return "LineInfo [%s|%s|%s|%s]" % (self.pre, self.esc, self.ifun, self.the_rest) |
|
|
| def __repr__(self) -> str: |
| return "<" + str(self) + ">" |
|
|