Add files using upload-large-folder tool
Browse files- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/__init__.py +82 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/__main__.py +17 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/cmdline.py +668 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/console.py +70 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/filter.py +70 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/formatter.py +129 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/lexer.py +963 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/plugin.py +74 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/regexopt.py +102 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/scanner.py +104 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/sphinxext.py +247 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/style.py +203 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/token.py +214 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/unistring.py +153 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/util.py +324 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/shellingham/posix/__init__.py +112 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/shellingham/posix/ps.py +51 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/aria/__init__.py +31 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/aria/modular_aria.py +1156 -0
- LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/timesformer/modeling_timesformer.py +751 -0
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/__init__.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Pygments
|
| 3 |
+
~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Pygments is a syntax highlighting package written in Python.
|
| 6 |
+
|
| 7 |
+
It is a generic syntax highlighter for general use in all kinds of software
|
| 8 |
+
such as forum systems, wikis or other applications that need to prettify
|
| 9 |
+
source code. Highlights are:
|
| 10 |
+
|
| 11 |
+
* a wide range of common languages and markup formats is supported
|
| 12 |
+
* special attention is paid to details, increasing quality by a fair amount
|
| 13 |
+
* support for new languages and formats are added easily
|
| 14 |
+
* a number of output formats, presently HTML, LaTeX, RTF, SVG, all image
|
| 15 |
+
formats that PIL supports, and ANSI sequences
|
| 16 |
+
* it is usable as a command-line tool and as a library
|
| 17 |
+
* ... and it highlights even Brainfuck!
|
| 18 |
+
|
| 19 |
+
The `Pygments master branch`_ is installable with ``easy_install Pygments==dev``.
|
| 20 |
+
|
| 21 |
+
.. _Pygments master branch:
|
| 22 |
+
https://github.com/pygments/pygments/archive/master.zip#egg=Pygments-dev
|
| 23 |
+
|
| 24 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 25 |
+
:license: BSD, see LICENSE for details.
|
| 26 |
+
"""
|
| 27 |
+
from io import StringIO, BytesIO
|
| 28 |
+
|
| 29 |
+
__version__ = '2.20.0'
|
| 30 |
+
__docformat__ = 'restructuredtext'
|
| 31 |
+
|
| 32 |
+
__all__ = ['lex', 'format', 'highlight']
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def lex(code, lexer):
|
| 36 |
+
"""
|
| 37 |
+
Lex `code` with the `lexer` (must be a `Lexer` instance)
|
| 38 |
+
and return an iterable of tokens. Currently, this only calls
|
| 39 |
+
`lexer.get_tokens()`.
|
| 40 |
+
"""
|
| 41 |
+
try:
|
| 42 |
+
return lexer.get_tokens(code)
|
| 43 |
+
except TypeError:
|
| 44 |
+
# Heuristic to catch a common mistake.
|
| 45 |
+
from pygments.lexer import RegexLexer
|
| 46 |
+
if isinstance(lexer, type) and issubclass(lexer, RegexLexer):
|
| 47 |
+
raise TypeError('lex() argument must be a lexer instance, '
|
| 48 |
+
'not a class')
|
| 49 |
+
raise
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def format(tokens, formatter, outfile=None): # pylint: disable=redefined-builtin
|
| 53 |
+
"""
|
| 54 |
+
Format ``tokens`` (an iterable of tokens) with the formatter ``formatter``
|
| 55 |
+
(a `Formatter` instance).
|
| 56 |
+
|
| 57 |
+
If ``outfile`` is given and a valid file object (an object with a
|
| 58 |
+
``write`` method), the result will be written to it, otherwise it
|
| 59 |
+
is returned as a string.
|
| 60 |
+
"""
|
| 61 |
+
try:
|
| 62 |
+
if not outfile:
|
| 63 |
+
realoutfile = getattr(formatter, 'encoding', None) and BytesIO() or StringIO()
|
| 64 |
+
formatter.format(tokens, realoutfile)
|
| 65 |
+
return realoutfile.getvalue()
|
| 66 |
+
else:
|
| 67 |
+
formatter.format(tokens, outfile)
|
| 68 |
+
except TypeError:
|
| 69 |
+
# Heuristic to catch a common mistake.
|
| 70 |
+
from pygments.formatter import Formatter
|
| 71 |
+
if isinstance(formatter, type) and issubclass(formatter, Formatter):
|
| 72 |
+
raise TypeError('format() argument must be a formatter instance, '
|
| 73 |
+
'not a class')
|
| 74 |
+
raise
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def highlight(code, lexer, formatter, outfile=None):
|
| 78 |
+
"""
|
| 79 |
+
This is the most high-level highlighting function. It combines `lex` and
|
| 80 |
+
`format` in one function.
|
| 81 |
+
"""
|
| 82 |
+
return format(lex(code, lexer), formatter, outfile)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/__main__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.__main__
|
| 3 |
+
~~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Main entry point for ``python -m pygments``.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import sys
|
| 12 |
+
import pygments.cmdline
|
| 13 |
+
|
| 14 |
+
try:
|
| 15 |
+
sys.exit(pygments.cmdline.main(sys.argv))
|
| 16 |
+
except KeyboardInterrupt:
|
| 17 |
+
sys.exit(1)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/cmdline.py
ADDED
|
@@ -0,0 +1,668 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.cmdline
|
| 3 |
+
~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Command line interface.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import os
|
| 12 |
+
import sys
|
| 13 |
+
import shutil
|
| 14 |
+
import argparse
|
| 15 |
+
from textwrap import dedent
|
| 16 |
+
|
| 17 |
+
from pygments import __version__, highlight
|
| 18 |
+
from pygments.util import ClassNotFound, OptionError, docstring_headline, \
|
| 19 |
+
guess_decode, guess_decode_from_terminal, terminal_encoding, \
|
| 20 |
+
UnclosingTextIOWrapper
|
| 21 |
+
from pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer, \
|
| 22 |
+
load_lexer_from_file, get_lexer_for_filename, find_lexer_class_for_filename
|
| 23 |
+
from pygments.lexers.special import TextLexer
|
| 24 |
+
from pygments.formatters.latex import LatexEmbeddedLexer, LatexFormatter
|
| 25 |
+
from pygments.formatters import get_all_formatters, get_formatter_by_name, \
|
| 26 |
+
load_formatter_from_file, get_formatter_for_filename, find_formatter_class
|
| 27 |
+
from pygments.formatters.terminal import TerminalFormatter
|
| 28 |
+
from pygments.formatters.terminal256 import Terminal256Formatter, TerminalTrueColorFormatter
|
| 29 |
+
from pygments.filters import get_all_filters, find_filter_class
|
| 30 |
+
from pygments.styles import get_all_styles, get_style_by_name
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def _parse_options(o_strs):
|
| 34 |
+
opts = {}
|
| 35 |
+
if not o_strs:
|
| 36 |
+
return opts
|
| 37 |
+
for o_str in o_strs:
|
| 38 |
+
if not o_str.strip():
|
| 39 |
+
continue
|
| 40 |
+
o_args = o_str.split(',')
|
| 41 |
+
for o_arg in o_args:
|
| 42 |
+
o_arg = o_arg.strip()
|
| 43 |
+
try:
|
| 44 |
+
o_key, o_val = o_arg.split('=', 1)
|
| 45 |
+
o_key = o_key.strip()
|
| 46 |
+
o_val = o_val.strip()
|
| 47 |
+
except ValueError:
|
| 48 |
+
opts[o_arg] = True
|
| 49 |
+
else:
|
| 50 |
+
opts[o_key] = o_val
|
| 51 |
+
return opts
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def _parse_filters(f_strs):
|
| 55 |
+
filters = []
|
| 56 |
+
if not f_strs:
|
| 57 |
+
return filters
|
| 58 |
+
for f_str in f_strs:
|
| 59 |
+
if ':' in f_str:
|
| 60 |
+
fname, fopts = f_str.split(':', 1)
|
| 61 |
+
filters.append((fname, _parse_options([fopts])))
|
| 62 |
+
else:
|
| 63 |
+
filters.append((f_str, {}))
|
| 64 |
+
return filters
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def _print_help(what, name):
|
| 68 |
+
try:
|
| 69 |
+
if what == 'lexer':
|
| 70 |
+
cls = get_lexer_by_name(name)
|
| 71 |
+
print(f"Help on the {cls.name} lexer:")
|
| 72 |
+
print(dedent(cls.__doc__))
|
| 73 |
+
elif what == 'formatter':
|
| 74 |
+
cls = find_formatter_class(name)
|
| 75 |
+
print(f"Help on the {cls.name} formatter:")
|
| 76 |
+
print(dedent(cls.__doc__))
|
| 77 |
+
elif what == 'filter':
|
| 78 |
+
cls = find_filter_class(name)
|
| 79 |
+
print(f"Help on the {name} filter:")
|
| 80 |
+
print(dedent(cls.__doc__))
|
| 81 |
+
return 0
|
| 82 |
+
except (AttributeError, ValueError):
|
| 83 |
+
print(f"{what} not found!", file=sys.stderr)
|
| 84 |
+
return 1
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def _print_list(what):
|
| 88 |
+
if what == 'lexer':
|
| 89 |
+
print()
|
| 90 |
+
print("Lexers:")
|
| 91 |
+
print("~~~~~~~")
|
| 92 |
+
|
| 93 |
+
info = []
|
| 94 |
+
for fullname, names, exts, _ in get_all_lexers():
|
| 95 |
+
tup = (', '.join(names)+':', fullname,
|
| 96 |
+
exts and '(filenames ' + ', '.join(exts) + ')' or '')
|
| 97 |
+
info.append(tup)
|
| 98 |
+
info.sort()
|
| 99 |
+
for i in info:
|
| 100 |
+
print(('* {}\n {} {}').format(*i))
|
| 101 |
+
|
| 102 |
+
elif what == 'formatter':
|
| 103 |
+
print()
|
| 104 |
+
print("Formatters:")
|
| 105 |
+
print("~~~~~~~~~~~")
|
| 106 |
+
|
| 107 |
+
info = []
|
| 108 |
+
for cls in get_all_formatters():
|
| 109 |
+
doc = docstring_headline(cls)
|
| 110 |
+
tup = (', '.join(cls.aliases) + ':', doc, cls.filenames and
|
| 111 |
+
'(filenames ' + ', '.join(cls.filenames) + ')' or '')
|
| 112 |
+
info.append(tup)
|
| 113 |
+
info.sort()
|
| 114 |
+
for i in info:
|
| 115 |
+
print(('* {}\n {} {}').format(*i))
|
| 116 |
+
|
| 117 |
+
elif what == 'filter':
|
| 118 |
+
print()
|
| 119 |
+
print("Filters:")
|
| 120 |
+
print("~~~~~~~~")
|
| 121 |
+
|
| 122 |
+
for name in get_all_filters():
|
| 123 |
+
cls = find_filter_class(name)
|
| 124 |
+
print("* " + name + ':')
|
| 125 |
+
print(f" {docstring_headline(cls)}")
|
| 126 |
+
|
| 127 |
+
elif what == 'style':
|
| 128 |
+
print()
|
| 129 |
+
print("Styles:")
|
| 130 |
+
print("~~~~~~~")
|
| 131 |
+
|
| 132 |
+
for name in get_all_styles():
|
| 133 |
+
cls = get_style_by_name(name)
|
| 134 |
+
print("* " + name + ':')
|
| 135 |
+
print(f" {docstring_headline(cls)}")
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def _print_list_as_json(requested_items):
|
| 139 |
+
import json
|
| 140 |
+
result = {}
|
| 141 |
+
if 'lexer' in requested_items:
|
| 142 |
+
info = {}
|
| 143 |
+
for fullname, names, filenames, mimetypes in get_all_lexers():
|
| 144 |
+
info[fullname] = {
|
| 145 |
+
'aliases': names,
|
| 146 |
+
'filenames': filenames,
|
| 147 |
+
'mimetypes': mimetypes
|
| 148 |
+
}
|
| 149 |
+
result['lexers'] = info
|
| 150 |
+
|
| 151 |
+
if 'formatter' in requested_items:
|
| 152 |
+
info = {}
|
| 153 |
+
for cls in get_all_formatters():
|
| 154 |
+
doc = docstring_headline(cls)
|
| 155 |
+
info[cls.name] = {
|
| 156 |
+
'aliases': cls.aliases,
|
| 157 |
+
'filenames': cls.filenames,
|
| 158 |
+
'doc': doc
|
| 159 |
+
}
|
| 160 |
+
result['formatters'] = info
|
| 161 |
+
|
| 162 |
+
if 'filter' in requested_items:
|
| 163 |
+
info = {}
|
| 164 |
+
for name in get_all_filters():
|
| 165 |
+
cls = find_filter_class(name)
|
| 166 |
+
info[name] = {
|
| 167 |
+
'doc': docstring_headline(cls)
|
| 168 |
+
}
|
| 169 |
+
result['filters'] = info
|
| 170 |
+
|
| 171 |
+
if 'style' in requested_items:
|
| 172 |
+
info = {}
|
| 173 |
+
for name in get_all_styles():
|
| 174 |
+
cls = get_style_by_name(name)
|
| 175 |
+
info[name] = {
|
| 176 |
+
'doc': docstring_headline(cls)
|
| 177 |
+
}
|
| 178 |
+
result['styles'] = info
|
| 179 |
+
|
| 180 |
+
json.dump(result, sys.stdout)
|
| 181 |
+
|
| 182 |
+
def main_inner(parser, argns):
|
| 183 |
+
if argns.help:
|
| 184 |
+
parser.print_help()
|
| 185 |
+
return 0
|
| 186 |
+
|
| 187 |
+
if argns.V:
|
| 188 |
+
print(f'Pygments version {__version__}, (c) 2006-present by Georg Brandl, Matthäus '
|
| 189 |
+
'Chajdas and contributors.')
|
| 190 |
+
return 0
|
| 191 |
+
|
| 192 |
+
def is_only_option(opt):
|
| 193 |
+
return not any(v for (k, v) in vars(argns).items() if k != opt)
|
| 194 |
+
|
| 195 |
+
# handle ``pygmentize -L``
|
| 196 |
+
if argns.L is not None:
|
| 197 |
+
arg_set = set()
|
| 198 |
+
for k, v in vars(argns).items():
|
| 199 |
+
if v:
|
| 200 |
+
arg_set.add(k)
|
| 201 |
+
|
| 202 |
+
arg_set.discard('L')
|
| 203 |
+
arg_set.discard('json')
|
| 204 |
+
|
| 205 |
+
if arg_set:
|
| 206 |
+
parser.print_help(sys.stderr)
|
| 207 |
+
return 2
|
| 208 |
+
|
| 209 |
+
# print version
|
| 210 |
+
if not argns.json:
|
| 211 |
+
main(['', '-V'])
|
| 212 |
+
allowed_types = {'lexer', 'formatter', 'filter', 'style'}
|
| 213 |
+
largs = [arg.rstrip('s') for arg in argns.L]
|
| 214 |
+
if any(arg not in allowed_types for arg in largs):
|
| 215 |
+
parser.print_help(sys.stderr)
|
| 216 |
+
return 0
|
| 217 |
+
if not largs:
|
| 218 |
+
largs = allowed_types
|
| 219 |
+
if not argns.json:
|
| 220 |
+
for arg in largs:
|
| 221 |
+
_print_list(arg)
|
| 222 |
+
else:
|
| 223 |
+
_print_list_as_json(largs)
|
| 224 |
+
return 0
|
| 225 |
+
|
| 226 |
+
# handle ``pygmentize -H``
|
| 227 |
+
if argns.H:
|
| 228 |
+
if not is_only_option('H'):
|
| 229 |
+
parser.print_help(sys.stderr)
|
| 230 |
+
return 2
|
| 231 |
+
what, name = argns.H
|
| 232 |
+
if what not in ('lexer', 'formatter', 'filter'):
|
| 233 |
+
parser.print_help(sys.stderr)
|
| 234 |
+
return 2
|
| 235 |
+
return _print_help(what, name)
|
| 236 |
+
|
| 237 |
+
# parse -O options
|
| 238 |
+
parsed_opts = _parse_options(argns.O or [])
|
| 239 |
+
|
| 240 |
+
# parse -P options
|
| 241 |
+
for p_opt in argns.P or []:
|
| 242 |
+
try:
|
| 243 |
+
name, value = p_opt.split('=', 1)
|
| 244 |
+
except ValueError:
|
| 245 |
+
parsed_opts[p_opt] = True
|
| 246 |
+
else:
|
| 247 |
+
parsed_opts[name] = value
|
| 248 |
+
|
| 249 |
+
# encodings
|
| 250 |
+
inencoding = parsed_opts.get('inencoding', parsed_opts.get('encoding'))
|
| 251 |
+
outencoding = parsed_opts.get('outencoding', parsed_opts.get('encoding'))
|
| 252 |
+
|
| 253 |
+
# handle ``pygmentize -N``
|
| 254 |
+
if argns.N:
|
| 255 |
+
lexer = find_lexer_class_for_filename(argns.N)
|
| 256 |
+
if lexer is None:
|
| 257 |
+
lexer = TextLexer
|
| 258 |
+
|
| 259 |
+
print(lexer.aliases[0])
|
| 260 |
+
return 0
|
| 261 |
+
|
| 262 |
+
# handle ``pygmentize -C``
|
| 263 |
+
if argns.C:
|
| 264 |
+
inp = sys.stdin.buffer.read()
|
| 265 |
+
try:
|
| 266 |
+
lexer = guess_lexer(inp, inencoding=inencoding)
|
| 267 |
+
except ClassNotFound:
|
| 268 |
+
lexer = TextLexer
|
| 269 |
+
|
| 270 |
+
print(lexer.aliases[0])
|
| 271 |
+
return 0
|
| 272 |
+
|
| 273 |
+
# handle ``pygmentize -S``
|
| 274 |
+
S_opt = argns.S
|
| 275 |
+
a_opt = argns.a
|
| 276 |
+
if S_opt is not None:
|
| 277 |
+
f_opt = argns.f
|
| 278 |
+
if not f_opt:
|
| 279 |
+
parser.print_help(sys.stderr)
|
| 280 |
+
return 2
|
| 281 |
+
if argns.l or argns.INPUTFILE:
|
| 282 |
+
parser.print_help(sys.stderr)
|
| 283 |
+
return 2
|
| 284 |
+
|
| 285 |
+
try:
|
| 286 |
+
parsed_opts['style'] = S_opt
|
| 287 |
+
fmter = get_formatter_by_name(f_opt, **parsed_opts)
|
| 288 |
+
except ClassNotFound as err:
|
| 289 |
+
print(err, file=sys.stderr)
|
| 290 |
+
return 1
|
| 291 |
+
|
| 292 |
+
print(fmter.get_style_defs(a_opt or ''))
|
| 293 |
+
return 0
|
| 294 |
+
|
| 295 |
+
# if no -S is given, -a is not allowed
|
| 296 |
+
if argns.a is not None:
|
| 297 |
+
parser.print_help(sys.stderr)
|
| 298 |
+
return 2
|
| 299 |
+
|
| 300 |
+
# parse -F options
|
| 301 |
+
F_opts = _parse_filters(argns.F or [])
|
| 302 |
+
|
| 303 |
+
# -x: allow custom (eXternal) lexers and formatters
|
| 304 |
+
allow_custom_lexer_formatter = bool(argns.x)
|
| 305 |
+
|
| 306 |
+
# select lexer
|
| 307 |
+
lexer = None
|
| 308 |
+
|
| 309 |
+
# given by name?
|
| 310 |
+
lexername = argns.l
|
| 311 |
+
if lexername:
|
| 312 |
+
# custom lexer, located relative to user's cwd
|
| 313 |
+
if allow_custom_lexer_formatter and '.py' in lexername:
|
| 314 |
+
try:
|
| 315 |
+
filename = None
|
| 316 |
+
name = None
|
| 317 |
+
if ':' in lexername:
|
| 318 |
+
filename, name = lexername.rsplit(':', 1)
|
| 319 |
+
|
| 320 |
+
if '.py' in name:
|
| 321 |
+
# This can happen on Windows: If the lexername is
|
| 322 |
+
# C:\lexer.py -- return to normal load path in that case
|
| 323 |
+
name = None
|
| 324 |
+
|
| 325 |
+
if filename and name:
|
| 326 |
+
lexer = load_lexer_from_file(filename, name,
|
| 327 |
+
**parsed_opts)
|
| 328 |
+
else:
|
| 329 |
+
lexer = load_lexer_from_file(lexername, **parsed_opts)
|
| 330 |
+
except ClassNotFound as err:
|
| 331 |
+
print('Error:', err, file=sys.stderr)
|
| 332 |
+
return 1
|
| 333 |
+
else:
|
| 334 |
+
try:
|
| 335 |
+
lexer = get_lexer_by_name(lexername, **parsed_opts)
|
| 336 |
+
except (OptionError, ClassNotFound) as err:
|
| 337 |
+
print('Error:', err, file=sys.stderr)
|
| 338 |
+
return 1
|
| 339 |
+
|
| 340 |
+
# read input code
|
| 341 |
+
code = None
|
| 342 |
+
|
| 343 |
+
if argns.INPUTFILE:
|
| 344 |
+
if argns.s:
|
| 345 |
+
print('Error: -s option not usable when input file specified',
|
| 346 |
+
file=sys.stderr)
|
| 347 |
+
return 2
|
| 348 |
+
|
| 349 |
+
infn = argns.INPUTFILE
|
| 350 |
+
try:
|
| 351 |
+
with open(infn, 'rb') as infp:
|
| 352 |
+
code = infp.read()
|
| 353 |
+
except Exception as err:
|
| 354 |
+
print('Error: cannot read infile:', err, file=sys.stderr)
|
| 355 |
+
return 1
|
| 356 |
+
if not inencoding:
|
| 357 |
+
code, inencoding = guess_decode(code)
|
| 358 |
+
|
| 359 |
+
# do we have to guess the lexer?
|
| 360 |
+
if not lexer:
|
| 361 |
+
try:
|
| 362 |
+
lexer = get_lexer_for_filename(infn, code, **parsed_opts)
|
| 363 |
+
except ClassNotFound as err:
|
| 364 |
+
if argns.g:
|
| 365 |
+
try:
|
| 366 |
+
lexer = guess_lexer(code, **parsed_opts)
|
| 367 |
+
except ClassNotFound:
|
| 368 |
+
lexer = TextLexer(**parsed_opts)
|
| 369 |
+
else:
|
| 370 |
+
print('Error:', err, file=sys.stderr)
|
| 371 |
+
return 1
|
| 372 |
+
except OptionError as err:
|
| 373 |
+
print('Error:', err, file=sys.stderr)
|
| 374 |
+
return 1
|
| 375 |
+
|
| 376 |
+
elif not argns.s: # treat stdin as full file (-s support is later)
|
| 377 |
+
# read code from terminal, always in binary mode since we want to
|
| 378 |
+
# decode ourselves and be tolerant with it
|
| 379 |
+
code = sys.stdin.buffer.read() # use .buffer to get a binary stream
|
| 380 |
+
if not inencoding:
|
| 381 |
+
code, inencoding = guess_decode_from_terminal(code, sys.stdin)
|
| 382 |
+
# else the lexer will do the decoding
|
| 383 |
+
if not lexer:
|
| 384 |
+
try:
|
| 385 |
+
lexer = guess_lexer(code, **parsed_opts)
|
| 386 |
+
except ClassNotFound:
|
| 387 |
+
lexer = TextLexer(**parsed_opts)
|
| 388 |
+
|
| 389 |
+
else: # -s option needs a lexer with -l
|
| 390 |
+
if not lexer:
|
| 391 |
+
print('Error: when using -s a lexer has to be selected with -l',
|
| 392 |
+
file=sys.stderr)
|
| 393 |
+
return 2
|
| 394 |
+
|
| 395 |
+
# process filters
|
| 396 |
+
for fname, fopts in F_opts:
|
| 397 |
+
try:
|
| 398 |
+
lexer.add_filter(fname, **fopts)
|
| 399 |
+
except ClassNotFound as err:
|
| 400 |
+
print('Error:', err, file=sys.stderr)
|
| 401 |
+
return 1
|
| 402 |
+
|
| 403 |
+
# select formatter
|
| 404 |
+
outfn = argns.o
|
| 405 |
+
fmter = argns.f
|
| 406 |
+
if fmter:
|
| 407 |
+
# custom formatter, located relative to user's cwd
|
| 408 |
+
if allow_custom_lexer_formatter and '.py' in fmter:
|
| 409 |
+
try:
|
| 410 |
+
filename = None
|
| 411 |
+
name = None
|
| 412 |
+
if ':' in fmter:
|
| 413 |
+
# Same logic as above for custom lexer
|
| 414 |
+
filename, name = fmter.rsplit(':', 1)
|
| 415 |
+
|
| 416 |
+
if '.py' in name:
|
| 417 |
+
name = None
|
| 418 |
+
|
| 419 |
+
if filename and name:
|
| 420 |
+
fmter = load_formatter_from_file(filename, name,
|
| 421 |
+
**parsed_opts)
|
| 422 |
+
else:
|
| 423 |
+
fmter = load_formatter_from_file(fmter, **parsed_opts)
|
| 424 |
+
except ClassNotFound as err:
|
| 425 |
+
print('Error:', err, file=sys.stderr)
|
| 426 |
+
return 1
|
| 427 |
+
else:
|
| 428 |
+
try:
|
| 429 |
+
fmter = get_formatter_by_name(fmter, **parsed_opts)
|
| 430 |
+
except (OptionError, ClassNotFound) as err:
|
| 431 |
+
print('Error:', err, file=sys.stderr)
|
| 432 |
+
return 1
|
| 433 |
+
|
| 434 |
+
if outfn:
|
| 435 |
+
if not fmter:
|
| 436 |
+
try:
|
| 437 |
+
fmter = get_formatter_for_filename(outfn, **parsed_opts)
|
| 438 |
+
except (OptionError, ClassNotFound) as err:
|
| 439 |
+
print('Error:', err, file=sys.stderr)
|
| 440 |
+
return 1
|
| 441 |
+
try:
|
| 442 |
+
outfile = open(outfn, 'wb')
|
| 443 |
+
except Exception as err:
|
| 444 |
+
print('Error: cannot open outfile:', err, file=sys.stderr)
|
| 445 |
+
return 1
|
| 446 |
+
else:
|
| 447 |
+
if not fmter:
|
| 448 |
+
if os.environ.get('COLORTERM','') in ('truecolor', '24bit'):
|
| 449 |
+
fmter = TerminalTrueColorFormatter(**parsed_opts)
|
| 450 |
+
elif '256' in os.environ.get('TERM', ''):
|
| 451 |
+
fmter = Terminal256Formatter(**parsed_opts)
|
| 452 |
+
else:
|
| 453 |
+
fmter = TerminalFormatter(**parsed_opts)
|
| 454 |
+
outfile = sys.stdout.buffer
|
| 455 |
+
|
| 456 |
+
# determine output encoding if not explicitly selected
|
| 457 |
+
if not outencoding:
|
| 458 |
+
if outfn:
|
| 459 |
+
# output file? use lexer encoding for now (can still be None)
|
| 460 |
+
fmter.encoding = inencoding
|
| 461 |
+
else:
|
| 462 |
+
# else use terminal encoding
|
| 463 |
+
fmter.encoding = terminal_encoding(sys.stdout)
|
| 464 |
+
|
| 465 |
+
# provide coloring under Windows, if possible
|
| 466 |
+
if not outfn and sys.platform in ('win32', 'cygwin') and \
|
| 467 |
+
fmter.name in ('Terminal', 'Terminal256'): # pragma: no cover
|
| 468 |
+
# unfortunately colorama doesn't support binary streams on Py3
|
| 469 |
+
outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding)
|
| 470 |
+
fmter.encoding = None
|
| 471 |
+
try:
|
| 472 |
+
import colorama.initialise
|
| 473 |
+
except ImportError:
|
| 474 |
+
pass
|
| 475 |
+
else:
|
| 476 |
+
outfile = colorama.initialise.wrap_stream(
|
| 477 |
+
outfile, convert=None, strip=None, autoreset=False, wrap=True)
|
| 478 |
+
|
| 479 |
+
# When using the LaTeX formatter and the option `escapeinside` is
|
| 480 |
+
# specified, we need a special lexer which collects escaped text
|
| 481 |
+
# before running the chosen language lexer.
|
| 482 |
+
escapeinside = parsed_opts.get('escapeinside', '')
|
| 483 |
+
if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter):
|
| 484 |
+
left = escapeinside[0]
|
| 485 |
+
right = escapeinside[1]
|
| 486 |
+
lexer = LatexEmbeddedLexer(left, right, lexer)
|
| 487 |
+
|
| 488 |
+
# ... and do it!
|
| 489 |
+
if not argns.s:
|
| 490 |
+
# process whole input as per normal...
|
| 491 |
+
try:
|
| 492 |
+
highlight(code, lexer, fmter, outfile)
|
| 493 |
+
finally:
|
| 494 |
+
if outfn:
|
| 495 |
+
outfile.close()
|
| 496 |
+
return 0
|
| 497 |
+
else:
|
| 498 |
+
# line by line processing of stdin (eg: for 'tail -f')...
|
| 499 |
+
try:
|
| 500 |
+
while 1:
|
| 501 |
+
line = sys.stdin.buffer.readline()
|
| 502 |
+
if not line:
|
| 503 |
+
break
|
| 504 |
+
if not inencoding:
|
| 505 |
+
line = guess_decode_from_terminal(line, sys.stdin)[0]
|
| 506 |
+
highlight(line, lexer, fmter, outfile)
|
| 507 |
+
if hasattr(outfile, 'flush'):
|
| 508 |
+
outfile.flush()
|
| 509 |
+
return 0
|
| 510 |
+
except KeyboardInterrupt: # pragma: no cover
|
| 511 |
+
return 0
|
| 512 |
+
finally:
|
| 513 |
+
if outfn:
|
| 514 |
+
outfile.close()
|
| 515 |
+
|
| 516 |
+
|
| 517 |
+
class HelpFormatter(argparse.HelpFormatter):
|
| 518 |
+
def __init__(self, prog, indent_increment=2, max_help_position=16, width=None):
|
| 519 |
+
if width is None:
|
| 520 |
+
try:
|
| 521 |
+
width = shutil.get_terminal_size().columns - 2
|
| 522 |
+
except Exception:
|
| 523 |
+
pass
|
| 524 |
+
argparse.HelpFormatter.__init__(self, prog, indent_increment,
|
| 525 |
+
max_help_position, width)
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
def main(args=sys.argv):
|
| 529 |
+
"""
|
| 530 |
+
Main command line entry point.
|
| 531 |
+
"""
|
| 532 |
+
desc = "Highlight an input file and write the result to an output file."
|
| 533 |
+
parser = argparse.ArgumentParser(description=desc, add_help=False,
|
| 534 |
+
formatter_class=HelpFormatter)
|
| 535 |
+
|
| 536 |
+
operation = parser.add_argument_group('Main operation')
|
| 537 |
+
lexersel = operation.add_mutually_exclusive_group()
|
| 538 |
+
lexersel.add_argument(
|
| 539 |
+
'-l', metavar='LEXER',
|
| 540 |
+
help='Specify the lexer to use. (Query names with -L.) If not '
|
| 541 |
+
'given and -g is not present, the lexer is guessed from the filename.')
|
| 542 |
+
lexersel.add_argument(
|
| 543 |
+
'-g', action='store_true',
|
| 544 |
+
help='Guess the lexer from the file contents, or pass through '
|
| 545 |
+
'as plain text if nothing can be guessed.')
|
| 546 |
+
operation.add_argument(
|
| 547 |
+
'-F', metavar='FILTER[:options]', action='append',
|
| 548 |
+
help='Add a filter to the token stream. (Query names with -L.) '
|
| 549 |
+
'Filter options are given after a colon if necessary.')
|
| 550 |
+
operation.add_argument(
|
| 551 |
+
'-f', metavar='FORMATTER',
|
| 552 |
+
help='Specify the formatter to use. (Query names with -L.) '
|
| 553 |
+
'If not given, the formatter is guessed from the output filename, '
|
| 554 |
+
'and defaults to the terminal formatter if the output is to the '
|
| 555 |
+
'terminal or an unknown file extension.')
|
| 556 |
+
operation.add_argument(
|
| 557 |
+
'-O', metavar='OPTION=value[,OPTION=value,...]', action='append',
|
| 558 |
+
help='Give options to the lexer and formatter as a comma-separated '
|
| 559 |
+
'list of key-value pairs. '
|
| 560 |
+
'Example: `-O bg=light,python=cool`.')
|
| 561 |
+
operation.add_argument(
|
| 562 |
+
'-P', metavar='OPTION=value', action='append',
|
| 563 |
+
help='Give a single option to the lexer and formatter - with this '
|
| 564 |
+
'you can pass options whose value contains commas and equal signs. '
|
| 565 |
+
'Example: `-P "heading=Pygments, the Python highlighter"`.')
|
| 566 |
+
operation.add_argument(
|
| 567 |
+
'-o', metavar='OUTPUTFILE',
|
| 568 |
+
help='Where to write the output. Defaults to standard output.')
|
| 569 |
+
|
| 570 |
+
operation.add_argument(
|
| 571 |
+
'INPUTFILE', nargs='?',
|
| 572 |
+
help='Where to read the input. Defaults to standard input.')
|
| 573 |
+
|
| 574 |
+
flags = parser.add_argument_group('Operation flags')
|
| 575 |
+
flags.add_argument(
|
| 576 |
+
'-v', action='store_true',
|
| 577 |
+
help='Print a detailed traceback on unhandled exceptions, which '
|
| 578 |
+
'is useful for debugging and bug reports.')
|
| 579 |
+
flags.add_argument(
|
| 580 |
+
'-s', action='store_true',
|
| 581 |
+
help='Process lines one at a time until EOF, rather than waiting to '
|
| 582 |
+
'process the entire file. This only works for stdin, only for lexers '
|
| 583 |
+
'with no line-spanning constructs, and is intended for streaming '
|
| 584 |
+
'input such as you get from `tail -f`. '
|
| 585 |
+
'Example usage: `tail -f sql.log | pygmentize -s -l sql`.')
|
| 586 |
+
flags.add_argument(
|
| 587 |
+
'-x', action='store_true',
|
| 588 |
+
help='Allow custom lexers and formatters to be loaded from a .py file '
|
| 589 |
+
'relative to the current working directory. For example, '
|
| 590 |
+
'`-l ./customlexer.py -x`. By default, this option expects a file '
|
| 591 |
+
'with a class named CustomLexer or CustomFormatter; you can also '
|
| 592 |
+
'specify your own class name with a colon (`-l ./lexer.py:MyLexer`). '
|
| 593 |
+
'Users should be very careful not to use this option with untrusted '
|
| 594 |
+
'files, because it will import and run them.')
|
| 595 |
+
flags.add_argument('--json', help='Output as JSON. This can '
|
| 596 |
+
'be only used in conjunction with -L.',
|
| 597 |
+
default=False,
|
| 598 |
+
action='store_true')
|
| 599 |
+
|
| 600 |
+
special_modes_group = parser.add_argument_group(
|
| 601 |
+
'Special modes - do not do any highlighting')
|
| 602 |
+
special_modes = special_modes_group.add_mutually_exclusive_group()
|
| 603 |
+
special_modes.add_argument(
|
| 604 |
+
'-S', metavar='STYLE -f formatter',
|
| 605 |
+
help='Print style definitions for STYLE for a formatter '
|
| 606 |
+
'given with -f. The argument given by -a is formatter '
|
| 607 |
+
'dependent.')
|
| 608 |
+
special_modes.add_argument(
|
| 609 |
+
'-L', nargs='*', metavar='WHAT',
|
| 610 |
+
help='List lexers, formatters, styles or filters -- '
|
| 611 |
+
'give additional arguments for the thing(s) you want to list '
|
| 612 |
+
'(e.g. "styles"), or omit them to list everything.')
|
| 613 |
+
special_modes.add_argument(
|
| 614 |
+
'-N', metavar='FILENAME',
|
| 615 |
+
help='Guess and print out a lexer name based solely on the given '
|
| 616 |
+
'filename. Does not take input or highlight anything. If no specific '
|
| 617 |
+
'lexer can be determined, "text" is printed.')
|
| 618 |
+
special_modes.add_argument(
|
| 619 |
+
'-C', action='store_true',
|
| 620 |
+
help='Like -N, but print out a lexer name based solely on '
|
| 621 |
+
'a given content from standard input.')
|
| 622 |
+
special_modes.add_argument(
|
| 623 |
+
'-H', action='store', nargs=2, metavar=('NAME', 'TYPE'),
|
| 624 |
+
help='Print detailed help for the object <name> of type <type>, '
|
| 625 |
+
'where <type> is one of "lexer", "formatter" or "filter".')
|
| 626 |
+
special_modes.add_argument(
|
| 627 |
+
'-V', action='store_true',
|
| 628 |
+
help='Print the package version.')
|
| 629 |
+
special_modes.add_argument(
|
| 630 |
+
'-h', '--help', action='store_true',
|
| 631 |
+
help='Print this help.')
|
| 632 |
+
special_modes_group.add_argument(
|
| 633 |
+
'-a', metavar='ARG',
|
| 634 |
+
help='Formatter-specific additional argument for the -S (print '
|
| 635 |
+
'style sheet) mode.')
|
| 636 |
+
|
| 637 |
+
argns = parser.parse_args(args[1:])
|
| 638 |
+
|
| 639 |
+
try:
|
| 640 |
+
return main_inner(parser, argns)
|
| 641 |
+
except BrokenPipeError:
|
| 642 |
+
# someone closed our stdout, e.g. by quitting a pager.
|
| 643 |
+
return 0
|
| 644 |
+
except Exception:
|
| 645 |
+
if argns.v:
|
| 646 |
+
print(file=sys.stderr)
|
| 647 |
+
print('*' * 65, file=sys.stderr)
|
| 648 |
+
print('An unhandled exception occurred while highlighting.',
|
| 649 |
+
file=sys.stderr)
|
| 650 |
+
print('Please report the whole traceback to the issue tracker at',
|
| 651 |
+
file=sys.stderr)
|
| 652 |
+
print('<https://github.com/pygments/pygments/issues>.',
|
| 653 |
+
file=sys.stderr)
|
| 654 |
+
print('*' * 65, file=sys.stderr)
|
| 655 |
+
print(file=sys.stderr)
|
| 656 |
+
raise
|
| 657 |
+
import traceback
|
| 658 |
+
info = traceback.format_exception(*sys.exc_info())
|
| 659 |
+
msg = info[-1].strip()
|
| 660 |
+
if len(info) >= 3:
|
| 661 |
+
# extract relevant file and position info
|
| 662 |
+
msg += '\n (f{})'.format(info[-2].split('\n')[0].strip()[1:])
|
| 663 |
+
print(file=sys.stderr)
|
| 664 |
+
print('*** Error while highlighting:', file=sys.stderr)
|
| 665 |
+
print(msg, file=sys.stderr)
|
| 666 |
+
print('*** If this is a bug you want to report, please rerun with -v.',
|
| 667 |
+
file=sys.stderr)
|
| 668 |
+
return 1
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/console.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.console
|
| 3 |
+
~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Format colored console output.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
esc = "\x1b["
|
| 12 |
+
|
| 13 |
+
codes = {}
|
| 14 |
+
codes[""] = ""
|
| 15 |
+
codes["reset"] = esc + "39;49;00m"
|
| 16 |
+
|
| 17 |
+
codes["bold"] = esc + "01m"
|
| 18 |
+
codes["faint"] = esc + "02m"
|
| 19 |
+
codes["standout"] = esc + "03m"
|
| 20 |
+
codes["underline"] = esc + "04m"
|
| 21 |
+
codes["blink"] = esc + "05m"
|
| 22 |
+
codes["overline"] = esc + "06m"
|
| 23 |
+
|
| 24 |
+
dark_colors = ["black", "red", "green", "yellow", "blue",
|
| 25 |
+
"magenta", "cyan", "gray"]
|
| 26 |
+
light_colors = ["brightblack", "brightred", "brightgreen", "brightyellow", "brightblue",
|
| 27 |
+
"brightmagenta", "brightcyan", "white"]
|
| 28 |
+
|
| 29 |
+
x = 30
|
| 30 |
+
for dark, light in zip(dark_colors, light_colors):
|
| 31 |
+
codes[dark] = esc + "%im" % x
|
| 32 |
+
codes[light] = esc + "%im" % (60 + x)
|
| 33 |
+
x += 1
|
| 34 |
+
|
| 35 |
+
del dark, light, x
|
| 36 |
+
|
| 37 |
+
codes["white"] = codes["bold"]
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def reset_color():
|
| 41 |
+
return codes["reset"]
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
def colorize(color_key, text):
|
| 45 |
+
return codes[color_key] + text + codes["reset"]
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def ansiformat(attr, text):
|
| 49 |
+
"""
|
| 50 |
+
Format ``text`` with a color and/or some attributes::
|
| 51 |
+
|
| 52 |
+
color normal color
|
| 53 |
+
*color* bold color
|
| 54 |
+
_color_ underlined color
|
| 55 |
+
+color+ blinking color
|
| 56 |
+
"""
|
| 57 |
+
result = []
|
| 58 |
+
if attr[:1] == attr[-1:] == '+':
|
| 59 |
+
result.append(codes['blink'])
|
| 60 |
+
attr = attr[1:-1]
|
| 61 |
+
if attr[:1] == attr[-1:] == '*':
|
| 62 |
+
result.append(codes['bold'])
|
| 63 |
+
attr = attr[1:-1]
|
| 64 |
+
if attr[:1] == attr[-1:] == '_':
|
| 65 |
+
result.append(codes['underline'])
|
| 66 |
+
attr = attr[1:-1]
|
| 67 |
+
result.append(codes[attr])
|
| 68 |
+
result.append(text)
|
| 69 |
+
result.append(codes['reset'])
|
| 70 |
+
return ''.join(result)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/filter.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.filter
|
| 3 |
+
~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Module that implements the default filter.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def apply_filters(stream, filters, lexer=None):
|
| 13 |
+
"""
|
| 14 |
+
Use this method to apply an iterable of filters to
|
| 15 |
+
a stream. If lexer is given it's forwarded to the
|
| 16 |
+
filter, otherwise the filter receives `None`.
|
| 17 |
+
"""
|
| 18 |
+
def _apply(filter_, stream):
|
| 19 |
+
yield from filter_.filter(lexer, stream)
|
| 20 |
+
for filter_ in filters:
|
| 21 |
+
stream = _apply(filter_, stream)
|
| 22 |
+
return stream
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def simplefilter(f):
|
| 26 |
+
"""
|
| 27 |
+
Decorator that converts a function into a filter::
|
| 28 |
+
|
| 29 |
+
@simplefilter
|
| 30 |
+
def lowercase(self, lexer, stream, options):
|
| 31 |
+
for ttype, value in stream:
|
| 32 |
+
yield ttype, value.lower()
|
| 33 |
+
"""
|
| 34 |
+
return type(f.__name__, (FunctionFilter,), {
|
| 35 |
+
'__module__': getattr(f, '__module__'),
|
| 36 |
+
'__doc__': f.__doc__,
|
| 37 |
+
'function': f,
|
| 38 |
+
})
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class Filter:
|
| 42 |
+
"""
|
| 43 |
+
Default filter. Subclass this class or use the `simplefilter`
|
| 44 |
+
decorator to create own filters.
|
| 45 |
+
"""
|
| 46 |
+
|
| 47 |
+
def __init__(self, **options):
|
| 48 |
+
self.options = options
|
| 49 |
+
|
| 50 |
+
def filter(self, lexer, stream):
|
| 51 |
+
raise NotImplementedError()
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class FunctionFilter(Filter):
|
| 55 |
+
"""
|
| 56 |
+
Abstract class used by `simplefilter` to create simple
|
| 57 |
+
function filters on the fly. The `simplefilter` decorator
|
| 58 |
+
automatically creates subclasses of this class for
|
| 59 |
+
functions passed to it.
|
| 60 |
+
"""
|
| 61 |
+
function = None
|
| 62 |
+
|
| 63 |
+
def __init__(self, **options):
|
| 64 |
+
if not hasattr(self, 'function'):
|
| 65 |
+
raise TypeError(f'{self.__class__.__name__!r} used without bound function')
|
| 66 |
+
Filter.__init__(self, **options)
|
| 67 |
+
|
| 68 |
+
def filter(self, lexer, stream):
|
| 69 |
+
# pylint: disable=not-callable
|
| 70 |
+
yield from self.function(lexer, stream, self.options)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/formatter.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.formatter
|
| 3 |
+
~~~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Base formatter class.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import codecs
|
| 12 |
+
|
| 13 |
+
from pygments.util import get_bool_opt
|
| 14 |
+
from pygments.styles import get_style_by_name
|
| 15 |
+
|
| 16 |
+
__all__ = ['Formatter']
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def _lookup_style(style):
|
| 20 |
+
if isinstance(style, str):
|
| 21 |
+
return get_style_by_name(style)
|
| 22 |
+
return style
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class Formatter:
|
| 26 |
+
"""
|
| 27 |
+
Converts a token stream to text.
|
| 28 |
+
|
| 29 |
+
Formatters should have attributes to help selecting them. These
|
| 30 |
+
are similar to the corresponding :class:`~pygments.lexer.Lexer`
|
| 31 |
+
attributes.
|
| 32 |
+
|
| 33 |
+
.. autoattribute:: name
|
| 34 |
+
:no-value:
|
| 35 |
+
|
| 36 |
+
.. autoattribute:: aliases
|
| 37 |
+
:no-value:
|
| 38 |
+
|
| 39 |
+
.. autoattribute:: filenames
|
| 40 |
+
:no-value:
|
| 41 |
+
|
| 42 |
+
You can pass options as keyword arguments to the constructor.
|
| 43 |
+
All formatters accept these basic options:
|
| 44 |
+
|
| 45 |
+
``style``
|
| 46 |
+
The style to use, can be a string or a Style subclass
|
| 47 |
+
(default: "default"). Not used by e.g. the
|
| 48 |
+
TerminalFormatter.
|
| 49 |
+
``full``
|
| 50 |
+
Tells the formatter to output a "full" document, i.e.
|
| 51 |
+
a complete self-contained document. This doesn't have
|
| 52 |
+
any effect for some formatters (default: false).
|
| 53 |
+
``title``
|
| 54 |
+
If ``full`` is true, the title that should be used to
|
| 55 |
+
caption the document (default: '').
|
| 56 |
+
``encoding``
|
| 57 |
+
If given, must be an encoding name. This will be used to
|
| 58 |
+
convert the Unicode token strings to byte strings in the
|
| 59 |
+
output. If it is "" or None, Unicode strings will be written
|
| 60 |
+
to the output file, which most file-like objects do not
|
| 61 |
+
support (default: None).
|
| 62 |
+
``outencoding``
|
| 63 |
+
Overrides ``encoding`` if given.
|
| 64 |
+
|
| 65 |
+
"""
|
| 66 |
+
|
| 67 |
+
#: Full name for the formatter, in human-readable form.
|
| 68 |
+
name = None
|
| 69 |
+
|
| 70 |
+
#: A list of short, unique identifiers that can be used to lookup
|
| 71 |
+
#: the formatter from a list, e.g. using :func:`.get_formatter_by_name()`.
|
| 72 |
+
aliases = []
|
| 73 |
+
|
| 74 |
+
#: A list of fnmatch patterns that match filenames for which this
|
| 75 |
+
#: formatter can produce output. The patterns in this list should be unique
|
| 76 |
+
#: among all formatters.
|
| 77 |
+
filenames = []
|
| 78 |
+
|
| 79 |
+
#: If True, this formatter outputs Unicode strings when no encoding
|
| 80 |
+
#: option is given.
|
| 81 |
+
unicodeoutput = True
|
| 82 |
+
|
| 83 |
+
def __init__(self, **options):
|
| 84 |
+
"""
|
| 85 |
+
As with lexers, this constructor takes arbitrary optional arguments,
|
| 86 |
+
and if you override it, you should first process your own options, then
|
| 87 |
+
call the base class implementation.
|
| 88 |
+
"""
|
| 89 |
+
self.style = _lookup_style(options.get('style', 'default'))
|
| 90 |
+
self.full = get_bool_opt(options, 'full', False)
|
| 91 |
+
self.title = options.get('title', '')
|
| 92 |
+
self.encoding = options.get('encoding', None) or None
|
| 93 |
+
if self.encoding in ('guess', 'chardet'):
|
| 94 |
+
# can happen for e.g. pygmentize -O encoding=guess
|
| 95 |
+
self.encoding = 'utf-8'
|
| 96 |
+
self.encoding = options.get('outencoding') or self.encoding
|
| 97 |
+
self.options = options
|
| 98 |
+
|
| 99 |
+
def get_style_defs(self, arg=''):
|
| 100 |
+
"""
|
| 101 |
+
This method must return statements or declarations suitable to define
|
| 102 |
+
the current style for subsequent highlighted text (e.g. CSS classes
|
| 103 |
+
in the `HTMLFormatter`).
|
| 104 |
+
|
| 105 |
+
The optional argument `arg` can be used to modify the generation and
|
| 106 |
+
is formatter dependent (it is standardized because it can be given on
|
| 107 |
+
the command line).
|
| 108 |
+
|
| 109 |
+
This method is called by the ``-S`` :doc:`command-line option <cmdline>`,
|
| 110 |
+
the `arg` is then given by the ``-a`` option.
|
| 111 |
+
"""
|
| 112 |
+
return ''
|
| 113 |
+
|
| 114 |
+
def format(self, tokensource, outfile):
|
| 115 |
+
"""
|
| 116 |
+
This method must format the tokens from the `tokensource` iterable and
|
| 117 |
+
write the formatted version to the file object `outfile`.
|
| 118 |
+
|
| 119 |
+
Formatter options can control how exactly the tokens are converted.
|
| 120 |
+
"""
|
| 121 |
+
if self.encoding:
|
| 122 |
+
# wrap the outfile in a StreamWriter
|
| 123 |
+
outfile = codecs.lookup(self.encoding)[3](outfile)
|
| 124 |
+
return self.format_unencoded(tokensource, outfile)
|
| 125 |
+
|
| 126 |
+
# Allow writing Formatter[str] or Formatter[bytes]. That's equivalent to
|
| 127 |
+
# Formatter. This helps when using third-party type stubs from typeshed.
|
| 128 |
+
def __class_getitem__(cls, name):
|
| 129 |
+
return cls
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/lexer.py
ADDED
|
@@ -0,0 +1,963 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.lexer
|
| 3 |
+
~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Base lexer classes.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import re
|
| 12 |
+
import sys
|
| 13 |
+
import time
|
| 14 |
+
|
| 15 |
+
from pygments.filter import apply_filters, Filter
|
| 16 |
+
from pygments.filters import get_filter_by_name
|
| 17 |
+
from pygments.token import Error, Text, Other, Whitespace, _TokenType
|
| 18 |
+
from pygments.util import get_bool_opt, get_int_opt, get_list_opt, \
|
| 19 |
+
make_analysator, Future, guess_decode
|
| 20 |
+
from pygments.regexopt import regex_opt
|
| 21 |
+
|
| 22 |
+
__all__ = ['Lexer', 'RegexLexer', 'ExtendedRegexLexer', 'DelegatingLexer',
|
| 23 |
+
'LexerContext', 'include', 'inherit', 'bygroups', 'using', 'this',
|
| 24 |
+
'default', 'words', 'line_re']
|
| 25 |
+
|
| 26 |
+
line_re = re.compile('.*?\n')
|
| 27 |
+
|
| 28 |
+
_encoding_map = [(b'\xef\xbb\xbf', 'utf-8'),
|
| 29 |
+
(b'\xff\xfe\0\0', 'utf-32'),
|
| 30 |
+
(b'\0\0\xfe\xff', 'utf-32be'),
|
| 31 |
+
(b'\xff\xfe', 'utf-16'),
|
| 32 |
+
(b'\xfe\xff', 'utf-16be')]
|
| 33 |
+
|
| 34 |
+
_default_analyse = staticmethod(lambda x: 0.0)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class LexerMeta(type):
|
| 38 |
+
"""
|
| 39 |
+
This metaclass automagically converts ``analyse_text`` methods into
|
| 40 |
+
static methods which always return float values.
|
| 41 |
+
"""
|
| 42 |
+
|
| 43 |
+
def __new__(mcs, name, bases, d):
|
| 44 |
+
if 'analyse_text' in d:
|
| 45 |
+
d['analyse_text'] = make_analysator(d['analyse_text'])
|
| 46 |
+
return type.__new__(mcs, name, bases, d)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class Lexer(metaclass=LexerMeta):
|
| 50 |
+
"""
|
| 51 |
+
Lexer for a specific language.
|
| 52 |
+
|
| 53 |
+
See also :doc:`lexerdevelopment`, a high-level guide to writing
|
| 54 |
+
lexers.
|
| 55 |
+
|
| 56 |
+
Lexer classes have attributes used for choosing the most appropriate
|
| 57 |
+
lexer based on various criteria.
|
| 58 |
+
|
| 59 |
+
.. autoattribute:: name
|
| 60 |
+
:no-value:
|
| 61 |
+
.. autoattribute:: aliases
|
| 62 |
+
:no-value:
|
| 63 |
+
.. autoattribute:: filenames
|
| 64 |
+
:no-value:
|
| 65 |
+
.. autoattribute:: alias_filenames
|
| 66 |
+
.. autoattribute:: mimetypes
|
| 67 |
+
:no-value:
|
| 68 |
+
.. autoattribute:: priority
|
| 69 |
+
|
| 70 |
+
Lexers included in Pygments should have two additional attributes:
|
| 71 |
+
|
| 72 |
+
.. autoattribute:: url
|
| 73 |
+
:no-value:
|
| 74 |
+
.. autoattribute:: version_added
|
| 75 |
+
:no-value:
|
| 76 |
+
|
| 77 |
+
Lexers included in Pygments may have additional attributes:
|
| 78 |
+
|
| 79 |
+
.. autoattribute:: _example
|
| 80 |
+
:no-value:
|
| 81 |
+
|
| 82 |
+
You can pass options to the constructor. The basic options recognized
|
| 83 |
+
by all lexers and processed by the base `Lexer` class are:
|
| 84 |
+
|
| 85 |
+
``stripnl``
|
| 86 |
+
Strip leading and trailing newlines from the input (default: True).
|
| 87 |
+
``stripall``
|
| 88 |
+
Strip all leading and trailing whitespace from the input
|
| 89 |
+
(default: False).
|
| 90 |
+
``ensurenl``
|
| 91 |
+
Make sure that the input ends with a newline (default: True). This
|
| 92 |
+
is required for some lexers that consume input linewise.
|
| 93 |
+
|
| 94 |
+
.. versionadded:: 1.3
|
| 95 |
+
|
| 96 |
+
``tabsize``
|
| 97 |
+
If given and greater than 0, expand tabs in the input (default: 0).
|
| 98 |
+
``encoding``
|
| 99 |
+
If given, must be an encoding name. This encoding will be used to
|
| 100 |
+
convert the input string to Unicode, if it is not already a Unicode
|
| 101 |
+
string (default: ``'guess'``, which uses a simple UTF-8 / Locale /
|
| 102 |
+
Latin1 detection. Can also be ``'chardet'`` to use the chardet
|
| 103 |
+
library, if it is installed.
|
| 104 |
+
``inencoding``
|
| 105 |
+
Overrides the ``encoding`` if given.
|
| 106 |
+
"""
|
| 107 |
+
|
| 108 |
+
#: Full name of the lexer, in human-readable form
|
| 109 |
+
name = None
|
| 110 |
+
|
| 111 |
+
#: A list of short, unique identifiers that can be used to look
|
| 112 |
+
#: up the lexer from a list, e.g., using `get_lexer_by_name()`.
|
| 113 |
+
aliases = []
|
| 114 |
+
|
| 115 |
+
#: A list of `fnmatch` patterns that match filenames which contain
|
| 116 |
+
#: content for this lexer. The patterns in this list should be unique among
|
| 117 |
+
#: all lexers.
|
| 118 |
+
filenames = []
|
| 119 |
+
|
| 120 |
+
#: A list of `fnmatch` patterns that match filenames which may or may not
|
| 121 |
+
#: contain content for this lexer. This list is used by the
|
| 122 |
+
#: :func:`.guess_lexer_for_filename()` function, to determine which lexers
|
| 123 |
+
#: are then included in guessing the correct one. That means that
|
| 124 |
+
#: e.g. every lexer for HTML and a template language should include
|
| 125 |
+
#: ``\*.html`` in this list.
|
| 126 |
+
alias_filenames = []
|
| 127 |
+
|
| 128 |
+
#: A list of MIME types for content that can be lexed with this lexer.
|
| 129 |
+
mimetypes = []
|
| 130 |
+
|
| 131 |
+
#: Priority, should multiple lexers match and no content is provided
|
| 132 |
+
priority = 0
|
| 133 |
+
|
| 134 |
+
#: URL of the language specification/definition. Used in the Pygments
|
| 135 |
+
#: documentation. Set to an empty string to disable.
|
| 136 |
+
url = None
|
| 137 |
+
|
| 138 |
+
#: Version of Pygments in which the lexer was added.
|
| 139 |
+
version_added = None
|
| 140 |
+
|
| 141 |
+
#: Example file name. Relative to the ``tests/examplefiles`` directory.
|
| 142 |
+
#: This is used by the documentation generator to show an example.
|
| 143 |
+
_example = None
|
| 144 |
+
|
| 145 |
+
def __init__(self, **options):
|
| 146 |
+
"""
|
| 147 |
+
This constructor takes arbitrary options as keyword arguments.
|
| 148 |
+
Every subclass must first process its own options and then call
|
| 149 |
+
the `Lexer` constructor, since it processes the basic
|
| 150 |
+
options like `stripnl`.
|
| 151 |
+
|
| 152 |
+
An example looks like this:
|
| 153 |
+
|
| 154 |
+
.. sourcecode:: python
|
| 155 |
+
|
| 156 |
+
def __init__(self, **options):
|
| 157 |
+
self.compress = options.get('compress', '')
|
| 158 |
+
Lexer.__init__(self, **options)
|
| 159 |
+
|
| 160 |
+
As these options must all be specifiable as strings (due to the
|
| 161 |
+
command line usage), there are various utility functions
|
| 162 |
+
available to help with that, see `Utilities`_.
|
| 163 |
+
"""
|
| 164 |
+
self.options = options
|
| 165 |
+
self.stripnl = get_bool_opt(options, 'stripnl', True)
|
| 166 |
+
self.stripall = get_bool_opt(options, 'stripall', False)
|
| 167 |
+
self.ensurenl = get_bool_opt(options, 'ensurenl', True)
|
| 168 |
+
self.tabsize = get_int_opt(options, 'tabsize', 0)
|
| 169 |
+
self.encoding = options.get('encoding', 'guess')
|
| 170 |
+
self.encoding = options.get('inencoding') or self.encoding
|
| 171 |
+
self.filters = []
|
| 172 |
+
for filter_ in get_list_opt(options, 'filters', ()):
|
| 173 |
+
self.add_filter(filter_)
|
| 174 |
+
|
| 175 |
+
def __repr__(self):
|
| 176 |
+
if self.options:
|
| 177 |
+
return f'<pygments.lexers.{self.__class__.__name__} with {self.options!r}>'
|
| 178 |
+
else:
|
| 179 |
+
return f'<pygments.lexers.{self.__class__.__name__}>'
|
| 180 |
+
|
| 181 |
+
def add_filter(self, filter_, **options):
|
| 182 |
+
"""
|
| 183 |
+
Add a new stream filter to this lexer.
|
| 184 |
+
"""
|
| 185 |
+
if not isinstance(filter_, Filter):
|
| 186 |
+
filter_ = get_filter_by_name(filter_, **options)
|
| 187 |
+
self.filters.append(filter_)
|
| 188 |
+
|
| 189 |
+
def analyse_text(text):
|
| 190 |
+
"""
|
| 191 |
+
A static method which is called for lexer guessing.
|
| 192 |
+
|
| 193 |
+
It should analyse the text and return a float in the range
|
| 194 |
+
from ``0.0`` to ``1.0``. If it returns ``0.0``, the lexer
|
| 195 |
+
will not be selected as the most probable one, if it returns
|
| 196 |
+
``1.0``, it will be selected immediately. This is used by
|
| 197 |
+
`guess_lexer`.
|
| 198 |
+
|
| 199 |
+
The `LexerMeta` metaclass automatically wraps this function so
|
| 200 |
+
that it works like a static method (no ``self`` or ``cls``
|
| 201 |
+
parameter) and the return value is automatically converted to
|
| 202 |
+
`float`. If the return value is an object that is boolean `False`
|
| 203 |
+
it's the same as if the return values was ``0.0``.
|
| 204 |
+
"""
|
| 205 |
+
|
| 206 |
+
def _preprocess_lexer_input(self, text):
|
| 207 |
+
"""Apply preprocessing such as decoding the input, removing BOM and normalizing newlines."""
|
| 208 |
+
|
| 209 |
+
if not isinstance(text, str):
|
| 210 |
+
if self.encoding == 'guess':
|
| 211 |
+
text, _ = guess_decode(text)
|
| 212 |
+
elif self.encoding == 'chardet':
|
| 213 |
+
try:
|
| 214 |
+
import chardet
|
| 215 |
+
except ImportError as e:
|
| 216 |
+
raise ImportError('To enable chardet encoding guessing, '
|
| 217 |
+
'please install the chardet library '
|
| 218 |
+
'from http://chardet.feedparser.org/') from e
|
| 219 |
+
# check for BOM first
|
| 220 |
+
decoded = None
|
| 221 |
+
for bom, encoding in _encoding_map:
|
| 222 |
+
if text.startswith(bom):
|
| 223 |
+
decoded = text[len(bom):].decode(encoding, 'replace')
|
| 224 |
+
break
|
| 225 |
+
# no BOM found, so use chardet
|
| 226 |
+
if decoded is None:
|
| 227 |
+
enc = chardet.detect(text[:1024]) # Guess using first 1KB
|
| 228 |
+
decoded = text.decode(enc.get('encoding') or 'utf-8',
|
| 229 |
+
'replace')
|
| 230 |
+
text = decoded
|
| 231 |
+
else:
|
| 232 |
+
text = text.decode(self.encoding)
|
| 233 |
+
if text.startswith('\ufeff'):
|
| 234 |
+
text = text[len('\ufeff'):]
|
| 235 |
+
else:
|
| 236 |
+
if text.startswith('\ufeff'):
|
| 237 |
+
text = text[len('\ufeff'):]
|
| 238 |
+
|
| 239 |
+
# text now *is* a unicode string
|
| 240 |
+
text = text.replace('\r\n', '\n')
|
| 241 |
+
text = text.replace('\r', '\n')
|
| 242 |
+
if self.stripall:
|
| 243 |
+
text = text.strip()
|
| 244 |
+
elif self.stripnl:
|
| 245 |
+
text = text.strip('\n')
|
| 246 |
+
if self.tabsize > 0:
|
| 247 |
+
text = text.expandtabs(self.tabsize)
|
| 248 |
+
if self.ensurenl and not text.endswith('\n'):
|
| 249 |
+
text += '\n'
|
| 250 |
+
|
| 251 |
+
return text
|
| 252 |
+
|
| 253 |
+
def get_tokens(self, text, unfiltered=False):
|
| 254 |
+
"""
|
| 255 |
+
This method is the basic interface of a lexer. It is called by
|
| 256 |
+
the `highlight()` function. It must process the text and return an
|
| 257 |
+
iterable of ``(tokentype, value)`` pairs from `text`.
|
| 258 |
+
|
| 259 |
+
Normally, you don't need to override this method. The default
|
| 260 |
+
implementation processes the options recognized by all lexers
|
| 261 |
+
(`stripnl`, `stripall` and so on), and then yields all tokens
|
| 262 |
+
from `get_tokens_unprocessed()`, with the ``index`` dropped.
|
| 263 |
+
|
| 264 |
+
If `unfiltered` is set to `True`, the filtering mechanism is
|
| 265 |
+
bypassed even if filters are defined.
|
| 266 |
+
"""
|
| 267 |
+
text = self._preprocess_lexer_input(text)
|
| 268 |
+
|
| 269 |
+
def streamer():
|
| 270 |
+
for _, t, v in self.get_tokens_unprocessed(text):
|
| 271 |
+
yield t, v
|
| 272 |
+
stream = streamer()
|
| 273 |
+
if not unfiltered:
|
| 274 |
+
stream = apply_filters(stream, self.filters, self)
|
| 275 |
+
return stream
|
| 276 |
+
|
| 277 |
+
def get_tokens_unprocessed(self, text):
|
| 278 |
+
"""
|
| 279 |
+
This method should process the text and return an iterable of
|
| 280 |
+
``(index, tokentype, value)`` tuples where ``index`` is the starting
|
| 281 |
+
position of the token within the input text.
|
| 282 |
+
|
| 283 |
+
It must be overridden by subclasses. It is recommended to
|
| 284 |
+
implement it as a generator to maximize effectiveness.
|
| 285 |
+
"""
|
| 286 |
+
raise NotImplementedError
|
| 287 |
+
|
| 288 |
+
|
| 289 |
+
class DelegatingLexer(Lexer):
|
| 290 |
+
"""
|
| 291 |
+
This lexer takes two lexer as arguments. A root lexer and
|
| 292 |
+
a language lexer. First everything is scanned using the language
|
| 293 |
+
lexer, afterwards all ``Other`` tokens are lexed using the root
|
| 294 |
+
lexer.
|
| 295 |
+
|
| 296 |
+
The lexers from the ``template`` lexer package use this base lexer.
|
| 297 |
+
"""
|
| 298 |
+
|
| 299 |
+
def __init__(self, _root_lexer, _language_lexer, _needle=Other, **options):
|
| 300 |
+
self.root_lexer = _root_lexer(**options)
|
| 301 |
+
self.language_lexer = _language_lexer(**options)
|
| 302 |
+
self.needle = _needle
|
| 303 |
+
Lexer.__init__(self, **options)
|
| 304 |
+
|
| 305 |
+
def get_tokens_unprocessed(self, text):
|
| 306 |
+
buffered = ''
|
| 307 |
+
insertions = []
|
| 308 |
+
lng_buffer = []
|
| 309 |
+
for i, t, v in self.language_lexer.get_tokens_unprocessed(text):
|
| 310 |
+
if t is self.needle:
|
| 311 |
+
if lng_buffer:
|
| 312 |
+
insertions.append((len(buffered), lng_buffer))
|
| 313 |
+
lng_buffer = []
|
| 314 |
+
buffered += v
|
| 315 |
+
else:
|
| 316 |
+
lng_buffer.append((i, t, v))
|
| 317 |
+
if lng_buffer:
|
| 318 |
+
insertions.append((len(buffered), lng_buffer))
|
| 319 |
+
return do_insertions(insertions,
|
| 320 |
+
self.root_lexer.get_tokens_unprocessed(buffered))
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
# ------------------------------------------------------------------------------
|
| 324 |
+
# RegexLexer and ExtendedRegexLexer
|
| 325 |
+
#
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
class include(str): # pylint: disable=invalid-name
|
| 329 |
+
"""
|
| 330 |
+
Indicates that a state should include rules from another state.
|
| 331 |
+
"""
|
| 332 |
+
pass
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
class _inherit:
|
| 336 |
+
"""
|
| 337 |
+
Indicates the a state should inherit from its superclass.
|
| 338 |
+
"""
|
| 339 |
+
def __repr__(self):
|
| 340 |
+
return 'inherit'
|
| 341 |
+
|
| 342 |
+
inherit = _inherit() # pylint: disable=invalid-name
|
| 343 |
+
|
| 344 |
+
|
| 345 |
+
class combined(tuple): # pylint: disable=invalid-name
|
| 346 |
+
"""
|
| 347 |
+
Indicates a state combined from multiple states.
|
| 348 |
+
"""
|
| 349 |
+
|
| 350 |
+
def __new__(cls, *args):
|
| 351 |
+
return tuple.__new__(cls, args)
|
| 352 |
+
|
| 353 |
+
def __init__(self, *args):
|
| 354 |
+
# tuple.__init__ doesn't do anything
|
| 355 |
+
pass
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
class _PseudoMatch:
|
| 359 |
+
"""
|
| 360 |
+
A pseudo match object constructed from a string.
|
| 361 |
+
"""
|
| 362 |
+
|
| 363 |
+
def __init__(self, start, text):
|
| 364 |
+
self._text = text
|
| 365 |
+
self._start = start
|
| 366 |
+
|
| 367 |
+
def start(self, arg=None):
|
| 368 |
+
return self._start
|
| 369 |
+
|
| 370 |
+
def end(self, arg=None):
|
| 371 |
+
return self._start + len(self._text)
|
| 372 |
+
|
| 373 |
+
def group(self, arg=None):
|
| 374 |
+
if arg:
|
| 375 |
+
raise IndexError('No such group')
|
| 376 |
+
return self._text
|
| 377 |
+
|
| 378 |
+
def groups(self):
|
| 379 |
+
return (self._text,)
|
| 380 |
+
|
| 381 |
+
def groupdict(self):
|
| 382 |
+
return {}
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
def bygroups(*args):
|
| 386 |
+
"""
|
| 387 |
+
Callback that yields multiple actions for each group in the match.
|
| 388 |
+
"""
|
| 389 |
+
def callback(lexer, match, ctx=None):
|
| 390 |
+
for i, action in enumerate(args):
|
| 391 |
+
if action is None:
|
| 392 |
+
continue
|
| 393 |
+
elif type(action) is _TokenType:
|
| 394 |
+
data = match.group(i + 1)
|
| 395 |
+
if data:
|
| 396 |
+
yield match.start(i + 1), action, data
|
| 397 |
+
else:
|
| 398 |
+
data = match.group(i + 1)
|
| 399 |
+
if data is not None:
|
| 400 |
+
if ctx:
|
| 401 |
+
ctx.pos = match.start(i + 1)
|
| 402 |
+
for item in action(lexer,
|
| 403 |
+
_PseudoMatch(match.start(i + 1), data), ctx):
|
| 404 |
+
if item:
|
| 405 |
+
yield item
|
| 406 |
+
if ctx:
|
| 407 |
+
ctx.pos = match.end()
|
| 408 |
+
return callback
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
class _This:
|
| 412 |
+
"""
|
| 413 |
+
Special singleton used for indicating the caller class.
|
| 414 |
+
Used by ``using``.
|
| 415 |
+
"""
|
| 416 |
+
|
| 417 |
+
this = _This()
|
| 418 |
+
|
| 419 |
+
|
| 420 |
+
def using(_other, **kwargs):
|
| 421 |
+
"""
|
| 422 |
+
Callback that processes the match with a different lexer.
|
| 423 |
+
|
| 424 |
+
The keyword arguments are forwarded to the lexer, except `state` which
|
| 425 |
+
is handled separately.
|
| 426 |
+
|
| 427 |
+
`state` specifies the state that the new lexer will start in, and can
|
| 428 |
+
be an enumerable such as ('root', 'inline', 'string') or a simple
|
| 429 |
+
string which is assumed to be on top of the root state.
|
| 430 |
+
|
| 431 |
+
Note: For that to work, `_other` must not be an `ExtendedRegexLexer`.
|
| 432 |
+
"""
|
| 433 |
+
gt_kwargs = {}
|
| 434 |
+
if 'state' in kwargs:
|
| 435 |
+
s = kwargs.pop('state')
|
| 436 |
+
if isinstance(s, (list, tuple)):
|
| 437 |
+
gt_kwargs['stack'] = s
|
| 438 |
+
else:
|
| 439 |
+
gt_kwargs['stack'] = ('root', s)
|
| 440 |
+
|
| 441 |
+
if _other is this:
|
| 442 |
+
def callback(lexer, match, ctx=None):
|
| 443 |
+
# if keyword arguments are given the callback
|
| 444 |
+
# function has to create a new lexer instance
|
| 445 |
+
if kwargs:
|
| 446 |
+
# XXX: cache that somehow
|
| 447 |
+
d = dict(lexer.options)
|
| 448 |
+
d.update(kwargs)
|
| 449 |
+
lx = lexer.__class__(**d)
|
| 450 |
+
else:
|
| 451 |
+
lx = lexer
|
| 452 |
+
s = match.start()
|
| 453 |
+
for i, t, v in lx.get_tokens_unprocessed(match.group(), **gt_kwargs):
|
| 454 |
+
yield i + s, t, v
|
| 455 |
+
if ctx:
|
| 456 |
+
ctx.pos = match.end()
|
| 457 |
+
else:
|
| 458 |
+
def callback(lexer, match, ctx=None):
|
| 459 |
+
# XXX: cache that somehow
|
| 460 |
+
d = dict(lexer.options)
|
| 461 |
+
d.update(kwargs)
|
| 462 |
+
lx = _other(**d)
|
| 463 |
+
|
| 464 |
+
s = match.start()
|
| 465 |
+
for i, t, v in lx.get_tokens_unprocessed(match.group(), **gt_kwargs):
|
| 466 |
+
yield i + s, t, v
|
| 467 |
+
if ctx:
|
| 468 |
+
ctx.pos = match.end()
|
| 469 |
+
return callback
|
| 470 |
+
|
| 471 |
+
|
| 472 |
+
class default:
|
| 473 |
+
"""
|
| 474 |
+
Indicates a state or state action (e.g. #pop) to apply.
|
| 475 |
+
For example default('#pop') is equivalent to ('', Token, '#pop')
|
| 476 |
+
Note that state tuples may be used as well.
|
| 477 |
+
|
| 478 |
+
.. versionadded:: 2.0
|
| 479 |
+
"""
|
| 480 |
+
def __init__(self, state):
|
| 481 |
+
self.state = state
|
| 482 |
+
|
| 483 |
+
|
| 484 |
+
class words(Future):
|
| 485 |
+
"""
|
| 486 |
+
Indicates a list of literal words that is transformed into an optimized
|
| 487 |
+
regex that matches any of the words.
|
| 488 |
+
|
| 489 |
+
.. versionadded:: 2.0
|
| 490 |
+
"""
|
| 491 |
+
def __init__(self, words, prefix='', suffix=''):
|
| 492 |
+
self.words = words
|
| 493 |
+
self.prefix = prefix
|
| 494 |
+
self.suffix = suffix
|
| 495 |
+
|
| 496 |
+
def get(self):
|
| 497 |
+
return regex_opt(self.words, prefix=self.prefix, suffix=self.suffix)
|
| 498 |
+
|
| 499 |
+
|
| 500 |
+
class RegexLexerMeta(LexerMeta):
|
| 501 |
+
"""
|
| 502 |
+
Metaclass for RegexLexer, creates the self._tokens attribute from
|
| 503 |
+
self.tokens on the first instantiation.
|
| 504 |
+
"""
|
| 505 |
+
|
| 506 |
+
def _process_regex(cls, regex, rflags, state):
|
| 507 |
+
"""Preprocess the regular expression component of a token definition."""
|
| 508 |
+
if isinstance(regex, Future):
|
| 509 |
+
regex = regex.get()
|
| 510 |
+
return re.compile(regex, rflags).match
|
| 511 |
+
|
| 512 |
+
def _process_token(cls, token):
|
| 513 |
+
"""Preprocess the token component of a token definition."""
|
| 514 |
+
assert type(token) is _TokenType or callable(token), \
|
| 515 |
+
f'token type must be simple type or callable, not {token!r}'
|
| 516 |
+
return token
|
| 517 |
+
|
| 518 |
+
def _process_new_state(cls, new_state, unprocessed, processed):
|
| 519 |
+
"""Preprocess the state transition action of a token definition."""
|
| 520 |
+
if isinstance(new_state, str):
|
| 521 |
+
# an existing state
|
| 522 |
+
if new_state == '#pop':
|
| 523 |
+
return -1
|
| 524 |
+
elif new_state in unprocessed:
|
| 525 |
+
return (new_state,)
|
| 526 |
+
elif new_state == '#push':
|
| 527 |
+
return new_state
|
| 528 |
+
elif new_state[:5] == '#pop:':
|
| 529 |
+
return -int(new_state[5:])
|
| 530 |
+
else:
|
| 531 |
+
assert False, f'unknown new state {new_state!r}'
|
| 532 |
+
elif isinstance(new_state, combined):
|
| 533 |
+
# combine a new state from existing ones
|
| 534 |
+
tmp_state = '_tmp_%d' % cls._tmpname
|
| 535 |
+
cls._tmpname += 1
|
| 536 |
+
itokens = []
|
| 537 |
+
for istate in new_state:
|
| 538 |
+
assert istate != new_state, f'circular state ref {istate!r}'
|
| 539 |
+
itokens.extend(cls._process_state(unprocessed,
|
| 540 |
+
processed, istate))
|
| 541 |
+
processed[tmp_state] = itokens
|
| 542 |
+
return (tmp_state,)
|
| 543 |
+
elif isinstance(new_state, tuple):
|
| 544 |
+
# push more than one state
|
| 545 |
+
for istate in new_state:
|
| 546 |
+
assert (istate in unprocessed or
|
| 547 |
+
istate in ('#pop', '#push')), \
|
| 548 |
+
'unknown new state ' + istate
|
| 549 |
+
return new_state
|
| 550 |
+
else:
|
| 551 |
+
assert False, f'unknown new state def {new_state!r}'
|
| 552 |
+
|
| 553 |
+
def _process_state(cls, unprocessed, processed, state):
|
| 554 |
+
"""Preprocess a single state definition."""
|
| 555 |
+
assert isinstance(state, str), f"wrong state name {state!r}"
|
| 556 |
+
assert state[0] != '#', f"invalid state name {state!r}"
|
| 557 |
+
if state in processed:
|
| 558 |
+
return processed[state]
|
| 559 |
+
tokens = processed[state] = []
|
| 560 |
+
rflags = cls.flags
|
| 561 |
+
for tdef in unprocessed[state]:
|
| 562 |
+
if isinstance(tdef, include):
|
| 563 |
+
# it's a state reference
|
| 564 |
+
assert tdef != state, f"circular state reference {state!r}"
|
| 565 |
+
tokens.extend(cls._process_state(unprocessed, processed,
|
| 566 |
+
str(tdef)))
|
| 567 |
+
continue
|
| 568 |
+
if isinstance(tdef, _inherit):
|
| 569 |
+
# should be processed already, but may not in the case of:
|
| 570 |
+
# 1. the state has no counterpart in any parent
|
| 571 |
+
# 2. the state includes more than one 'inherit'
|
| 572 |
+
continue
|
| 573 |
+
if isinstance(tdef, default):
|
| 574 |
+
new_state = cls._process_new_state(tdef.state, unprocessed, processed)
|
| 575 |
+
tokens.append((re.compile('').match, None, new_state))
|
| 576 |
+
continue
|
| 577 |
+
|
| 578 |
+
assert type(tdef) is tuple, f"wrong rule def {tdef!r}"
|
| 579 |
+
|
| 580 |
+
try:
|
| 581 |
+
rex = cls._process_regex(tdef[0], rflags, state)
|
| 582 |
+
except Exception as err:
|
| 583 |
+
raise ValueError(f"uncompilable regex {tdef[0]!r} in state {state!r} of {cls!r}: {err}") from err
|
| 584 |
+
|
| 585 |
+
token = cls._process_token(tdef[1])
|
| 586 |
+
|
| 587 |
+
if len(tdef) == 2:
|
| 588 |
+
new_state = None
|
| 589 |
+
else:
|
| 590 |
+
new_state = cls._process_new_state(tdef[2],
|
| 591 |
+
unprocessed, processed)
|
| 592 |
+
|
| 593 |
+
tokens.append((rex, token, new_state))
|
| 594 |
+
return tokens
|
| 595 |
+
|
| 596 |
+
def process_tokendef(cls, name, tokendefs=None):
|
| 597 |
+
"""Preprocess a dictionary of token definitions."""
|
| 598 |
+
processed = cls._all_tokens[name] = {}
|
| 599 |
+
tokendefs = tokendefs or cls.tokens[name]
|
| 600 |
+
for state in list(tokendefs):
|
| 601 |
+
cls._process_state(tokendefs, processed, state)
|
| 602 |
+
return processed
|
| 603 |
+
|
| 604 |
+
def get_tokendefs(cls):
|
| 605 |
+
"""
|
| 606 |
+
Merge tokens from superclasses in MRO order, returning a single tokendef
|
| 607 |
+
dictionary.
|
| 608 |
+
|
| 609 |
+
Any state that is not defined by a subclass will be inherited
|
| 610 |
+
automatically. States that *are* defined by subclasses will, by
|
| 611 |
+
default, override that state in the superclass. If a subclass wishes to
|
| 612 |
+
inherit definitions from a superclass, it can use the special value
|
| 613 |
+
"inherit", which will cause the superclass' state definition to be
|
| 614 |
+
included at that point in the state.
|
| 615 |
+
"""
|
| 616 |
+
tokens = {}
|
| 617 |
+
inheritable = {}
|
| 618 |
+
for c in cls.__mro__:
|
| 619 |
+
toks = c.__dict__.get('tokens', {})
|
| 620 |
+
|
| 621 |
+
for state, items in toks.items():
|
| 622 |
+
curitems = tokens.get(state)
|
| 623 |
+
if curitems is None:
|
| 624 |
+
# N.b. because this is assigned by reference, sufficiently
|
| 625 |
+
# deep hierarchies are processed incrementally (e.g. for
|
| 626 |
+
# A(B), B(C), C(RegexLexer), B will be premodified so X(B)
|
| 627 |
+
# will not see any inherits in B).
|
| 628 |
+
tokens[state] = items
|
| 629 |
+
try:
|
| 630 |
+
inherit_ndx = items.index(inherit)
|
| 631 |
+
except ValueError:
|
| 632 |
+
continue
|
| 633 |
+
inheritable[state] = inherit_ndx
|
| 634 |
+
continue
|
| 635 |
+
|
| 636 |
+
inherit_ndx = inheritable.pop(state, None)
|
| 637 |
+
if inherit_ndx is None:
|
| 638 |
+
continue
|
| 639 |
+
|
| 640 |
+
# Replace the "inherit" value with the items
|
| 641 |
+
curitems[inherit_ndx:inherit_ndx+1] = items
|
| 642 |
+
try:
|
| 643 |
+
# N.b. this is the index in items (that is, the superclass
|
| 644 |
+
# copy), so offset required when storing below.
|
| 645 |
+
new_inh_ndx = items.index(inherit)
|
| 646 |
+
except ValueError:
|
| 647 |
+
pass
|
| 648 |
+
else:
|
| 649 |
+
inheritable[state] = inherit_ndx + new_inh_ndx
|
| 650 |
+
|
| 651 |
+
return tokens
|
| 652 |
+
|
| 653 |
+
def __call__(cls, *args, **kwds):
|
| 654 |
+
"""Instantiate cls after preprocessing its token definitions."""
|
| 655 |
+
if '_tokens' not in cls.__dict__:
|
| 656 |
+
cls._all_tokens = {}
|
| 657 |
+
cls._tmpname = 0
|
| 658 |
+
if hasattr(cls, 'token_variants') and cls.token_variants:
|
| 659 |
+
# don't process yet
|
| 660 |
+
pass
|
| 661 |
+
else:
|
| 662 |
+
cls._tokens = cls.process_tokendef('', cls.get_tokendefs())
|
| 663 |
+
|
| 664 |
+
return type.__call__(cls, *args, **kwds)
|
| 665 |
+
|
| 666 |
+
|
| 667 |
+
class RegexLexer(Lexer, metaclass=RegexLexerMeta):
|
| 668 |
+
"""
|
| 669 |
+
Base for simple stateful regular expression-based lexers.
|
| 670 |
+
Simplifies the lexing process so that you need only
|
| 671 |
+
provide a list of states and regular expressions.
|
| 672 |
+
"""
|
| 673 |
+
|
| 674 |
+
#: Flags for compiling the regular expressions.
|
| 675 |
+
#: Defaults to MULTILINE.
|
| 676 |
+
flags = re.MULTILINE
|
| 677 |
+
|
| 678 |
+
#: At all time there is a stack of states. Initially, the stack contains
|
| 679 |
+
#: a single state 'root'. The top of the stack is called "the current state".
|
| 680 |
+
#:
|
| 681 |
+
#: Dict of ``{'state': [(regex, tokentype, new_state), ...], ...}``
|
| 682 |
+
#:
|
| 683 |
+
#: ``new_state`` can be omitted to signify no state transition.
|
| 684 |
+
#: If ``new_state`` is a string, it is pushed on the stack. This ensure
|
| 685 |
+
#: the new current state is ``new_state``.
|
| 686 |
+
#: If ``new_state`` is a tuple of strings, all of those strings are pushed
|
| 687 |
+
#: on the stack and the current state will be the last element of the list.
|
| 688 |
+
#: ``new_state`` can also be ``combined('state1', 'state2', ...)``
|
| 689 |
+
#: to signify a new, anonymous state combined from the rules of two
|
| 690 |
+
#: or more existing ones.
|
| 691 |
+
#: Furthermore, it can be '#pop' to signify going back one step in
|
| 692 |
+
#: the state stack, or '#push' to push the current state on the stack
|
| 693 |
+
#: again. Note that if you push while in a combined state, the combined
|
| 694 |
+
#: state itself is pushed, and not only the state in which the rule is
|
| 695 |
+
#: defined.
|
| 696 |
+
#:
|
| 697 |
+
#: The tuple can also be replaced with ``include('state')``, in which
|
| 698 |
+
#: case the rules from the state named by the string are included in the
|
| 699 |
+
#: current one.
|
| 700 |
+
tokens = {}
|
| 701 |
+
|
| 702 |
+
def get_tokens_unprocessed(self, text, stack=('root',)):
|
| 703 |
+
"""
|
| 704 |
+
Split ``text`` into (tokentype, text) pairs.
|
| 705 |
+
|
| 706 |
+
``stack`` is the initial stack (default: ``['root']``)
|
| 707 |
+
"""
|
| 708 |
+
pos = 0
|
| 709 |
+
tokendefs = self._tokens
|
| 710 |
+
statestack = list(stack)
|
| 711 |
+
statetokens = tokendefs[statestack[-1]]
|
| 712 |
+
while 1:
|
| 713 |
+
for rexmatch, action, new_state in statetokens:
|
| 714 |
+
m = rexmatch(text, pos)
|
| 715 |
+
if m:
|
| 716 |
+
if action is not None:
|
| 717 |
+
if type(action) is _TokenType:
|
| 718 |
+
yield pos, action, m.group()
|
| 719 |
+
else:
|
| 720 |
+
yield from action(self, m)
|
| 721 |
+
pos = m.end()
|
| 722 |
+
if new_state is not None:
|
| 723 |
+
# state transition
|
| 724 |
+
if isinstance(new_state, tuple):
|
| 725 |
+
for state in new_state:
|
| 726 |
+
if state == '#pop':
|
| 727 |
+
if len(statestack) > 1:
|
| 728 |
+
statestack.pop()
|
| 729 |
+
elif state == '#push':
|
| 730 |
+
statestack.append(statestack[-1])
|
| 731 |
+
else:
|
| 732 |
+
statestack.append(state)
|
| 733 |
+
elif isinstance(new_state, int):
|
| 734 |
+
# pop, but keep at least one state on the stack
|
| 735 |
+
# (random code leading to unexpected pops should
|
| 736 |
+
# not allow exceptions)
|
| 737 |
+
if abs(new_state) >= len(statestack):
|
| 738 |
+
del statestack[1:]
|
| 739 |
+
else:
|
| 740 |
+
del statestack[new_state:]
|
| 741 |
+
elif new_state == '#push':
|
| 742 |
+
statestack.append(statestack[-1])
|
| 743 |
+
else:
|
| 744 |
+
assert False, f"wrong state def: {new_state!r}"
|
| 745 |
+
statetokens = tokendefs[statestack[-1]]
|
| 746 |
+
break
|
| 747 |
+
else:
|
| 748 |
+
# We are here only if all state tokens have been considered
|
| 749 |
+
# and there was not a match on any of them.
|
| 750 |
+
try:
|
| 751 |
+
if text[pos] == '\n':
|
| 752 |
+
# at EOL, reset state to "root"
|
| 753 |
+
statestack = ['root']
|
| 754 |
+
statetokens = tokendefs['root']
|
| 755 |
+
yield pos, Whitespace, '\n'
|
| 756 |
+
pos += 1
|
| 757 |
+
continue
|
| 758 |
+
yield pos, Error, text[pos]
|
| 759 |
+
pos += 1
|
| 760 |
+
except IndexError:
|
| 761 |
+
break
|
| 762 |
+
|
| 763 |
+
|
| 764 |
+
class LexerContext:
|
| 765 |
+
"""
|
| 766 |
+
A helper object that holds lexer position data.
|
| 767 |
+
"""
|
| 768 |
+
|
| 769 |
+
def __init__(self, text, pos, stack=None, end=None):
|
| 770 |
+
self.text = text
|
| 771 |
+
self.pos = pos
|
| 772 |
+
self.end = end or len(text) # end=0 not supported ;-)
|
| 773 |
+
self.stack = stack or ['root']
|
| 774 |
+
|
| 775 |
+
def __repr__(self):
|
| 776 |
+
return f'LexerContext({self.text!r}, {self.pos!r}, {self.stack!r})'
|
| 777 |
+
|
| 778 |
+
|
| 779 |
+
class ExtendedRegexLexer(RegexLexer):
|
| 780 |
+
"""
|
| 781 |
+
A RegexLexer that uses a context object to store its state.
|
| 782 |
+
"""
|
| 783 |
+
|
| 784 |
+
def get_tokens_unprocessed(self, text=None, context=None):
|
| 785 |
+
"""
|
| 786 |
+
Split ``text`` into (tokentype, text) pairs.
|
| 787 |
+
If ``context`` is given, use this lexer context instead.
|
| 788 |
+
"""
|
| 789 |
+
tokendefs = self._tokens
|
| 790 |
+
if not context:
|
| 791 |
+
ctx = LexerContext(text, 0)
|
| 792 |
+
statetokens = tokendefs['root']
|
| 793 |
+
else:
|
| 794 |
+
ctx = context
|
| 795 |
+
statetokens = tokendefs[ctx.stack[-1]]
|
| 796 |
+
text = ctx.text
|
| 797 |
+
while 1:
|
| 798 |
+
for rexmatch, action, new_state in statetokens:
|
| 799 |
+
m = rexmatch(text, ctx.pos, ctx.end)
|
| 800 |
+
if m:
|
| 801 |
+
if action is not None:
|
| 802 |
+
if type(action) is _TokenType:
|
| 803 |
+
yield ctx.pos, action, m.group()
|
| 804 |
+
ctx.pos = m.end()
|
| 805 |
+
else:
|
| 806 |
+
yield from action(self, m, ctx)
|
| 807 |
+
if not new_state:
|
| 808 |
+
# altered the state stack?
|
| 809 |
+
statetokens = tokendefs[ctx.stack[-1]]
|
| 810 |
+
# CAUTION: callback must set ctx.pos!
|
| 811 |
+
if new_state is not None:
|
| 812 |
+
# state transition
|
| 813 |
+
if isinstance(new_state, tuple):
|
| 814 |
+
for state in new_state:
|
| 815 |
+
if state == '#pop':
|
| 816 |
+
if len(ctx.stack) > 1:
|
| 817 |
+
ctx.stack.pop()
|
| 818 |
+
elif state == '#push':
|
| 819 |
+
ctx.stack.append(ctx.stack[-1])
|
| 820 |
+
else:
|
| 821 |
+
ctx.stack.append(state)
|
| 822 |
+
elif isinstance(new_state, int):
|
| 823 |
+
# see RegexLexer for why this check is made
|
| 824 |
+
if abs(new_state) >= len(ctx.stack):
|
| 825 |
+
del ctx.stack[1:]
|
| 826 |
+
else:
|
| 827 |
+
del ctx.stack[new_state:]
|
| 828 |
+
elif new_state == '#push':
|
| 829 |
+
ctx.stack.append(ctx.stack[-1])
|
| 830 |
+
else:
|
| 831 |
+
assert False, f"wrong state def: {new_state!r}"
|
| 832 |
+
statetokens = tokendefs[ctx.stack[-1]]
|
| 833 |
+
break
|
| 834 |
+
else:
|
| 835 |
+
try:
|
| 836 |
+
if ctx.pos >= ctx.end:
|
| 837 |
+
break
|
| 838 |
+
if text[ctx.pos] == '\n':
|
| 839 |
+
# at EOL, reset state to "root"
|
| 840 |
+
ctx.stack = ['root']
|
| 841 |
+
statetokens = tokendefs['root']
|
| 842 |
+
yield ctx.pos, Text, '\n'
|
| 843 |
+
ctx.pos += 1
|
| 844 |
+
continue
|
| 845 |
+
yield ctx.pos, Error, text[ctx.pos]
|
| 846 |
+
ctx.pos += 1
|
| 847 |
+
except IndexError:
|
| 848 |
+
break
|
| 849 |
+
|
| 850 |
+
|
| 851 |
+
def do_insertions(insertions, tokens):
|
| 852 |
+
"""
|
| 853 |
+
Helper for lexers which must combine the results of several
|
| 854 |
+
sublexers.
|
| 855 |
+
|
| 856 |
+
``insertions`` is a list of ``(index, itokens)`` pairs.
|
| 857 |
+
Each ``itokens`` iterable should be inserted at position
|
| 858 |
+
``index`` into the token stream given by the ``tokens``
|
| 859 |
+
argument.
|
| 860 |
+
|
| 861 |
+
The result is a combined token stream.
|
| 862 |
+
|
| 863 |
+
TODO: clean up the code here.
|
| 864 |
+
"""
|
| 865 |
+
insertions = iter(insertions)
|
| 866 |
+
try:
|
| 867 |
+
index, itokens = next(insertions)
|
| 868 |
+
except StopIteration:
|
| 869 |
+
# no insertions
|
| 870 |
+
yield from tokens
|
| 871 |
+
return
|
| 872 |
+
|
| 873 |
+
realpos = None
|
| 874 |
+
insleft = True
|
| 875 |
+
|
| 876 |
+
# iterate over the token stream where we want to insert
|
| 877 |
+
# the tokens from the insertion list.
|
| 878 |
+
for i, t, v in tokens:
|
| 879 |
+
# first iteration. store the position of first item
|
| 880 |
+
if realpos is None:
|
| 881 |
+
realpos = i
|
| 882 |
+
oldi = 0
|
| 883 |
+
while insleft and i + len(v) >= index:
|
| 884 |
+
tmpval = v[oldi:index - i]
|
| 885 |
+
if tmpval:
|
| 886 |
+
yield realpos, t, tmpval
|
| 887 |
+
realpos += len(tmpval)
|
| 888 |
+
for it_index, it_token, it_value in itokens:
|
| 889 |
+
yield realpos, it_token, it_value
|
| 890 |
+
realpos += len(it_value)
|
| 891 |
+
oldi = index - i
|
| 892 |
+
try:
|
| 893 |
+
index, itokens = next(insertions)
|
| 894 |
+
except StopIteration:
|
| 895 |
+
insleft = False
|
| 896 |
+
break # not strictly necessary
|
| 897 |
+
if oldi < len(v):
|
| 898 |
+
yield realpos, t, v[oldi:]
|
| 899 |
+
realpos += len(v) - oldi
|
| 900 |
+
|
| 901 |
+
# leftover tokens
|
| 902 |
+
while insleft:
|
| 903 |
+
# no normal tokens, set realpos to zero
|
| 904 |
+
realpos = realpos or 0
|
| 905 |
+
for p, t, v in itokens:
|
| 906 |
+
yield realpos, t, v
|
| 907 |
+
realpos += len(v)
|
| 908 |
+
try:
|
| 909 |
+
index, itokens = next(insertions)
|
| 910 |
+
except StopIteration:
|
| 911 |
+
insleft = False
|
| 912 |
+
break # not strictly necessary
|
| 913 |
+
|
| 914 |
+
|
| 915 |
+
class ProfilingRegexLexerMeta(RegexLexerMeta):
|
| 916 |
+
"""Metaclass for ProfilingRegexLexer, collects regex timing info."""
|
| 917 |
+
|
| 918 |
+
def _process_regex(cls, regex, rflags, state):
|
| 919 |
+
if isinstance(regex, words):
|
| 920 |
+
rex = regex_opt(regex.words, prefix=regex.prefix,
|
| 921 |
+
suffix=regex.suffix)
|
| 922 |
+
else:
|
| 923 |
+
rex = regex
|
| 924 |
+
compiled = re.compile(rex, rflags)
|
| 925 |
+
|
| 926 |
+
def match_func(text, pos, endpos=sys.maxsize):
|
| 927 |
+
info = cls._prof_data[-1].setdefault((state, rex), [0, 0.0])
|
| 928 |
+
t0 = time.time()
|
| 929 |
+
res = compiled.match(text, pos, endpos)
|
| 930 |
+
t1 = time.time()
|
| 931 |
+
info[0] += 1
|
| 932 |
+
info[1] += t1 - t0
|
| 933 |
+
return res
|
| 934 |
+
return match_func
|
| 935 |
+
|
| 936 |
+
|
| 937 |
+
class ProfilingRegexLexer(RegexLexer, metaclass=ProfilingRegexLexerMeta):
|
| 938 |
+
"""Drop-in replacement for RegexLexer that does profiling of its regexes."""
|
| 939 |
+
|
| 940 |
+
_prof_data = []
|
| 941 |
+
_prof_sort_index = 4 # defaults to time per call
|
| 942 |
+
|
| 943 |
+
def get_tokens_unprocessed(self, text, stack=('root',)):
|
| 944 |
+
# this needs to be a stack, since using(this) will produce nested calls
|
| 945 |
+
self.__class__._prof_data.append({})
|
| 946 |
+
yield from RegexLexer.get_tokens_unprocessed(self, text, stack)
|
| 947 |
+
rawdata = self.__class__._prof_data.pop()
|
| 948 |
+
data = sorted(((s, repr(r).strip('u\'').replace('\\\\', '\\')[:65],
|
| 949 |
+
n, 1000 * t, 1000 * t / n)
|
| 950 |
+
for ((s, r), (n, t)) in rawdata.items()),
|
| 951 |
+
key=lambda x: x[self._prof_sort_index],
|
| 952 |
+
reverse=True)
|
| 953 |
+
sum_total = sum(x[3] for x in data)
|
| 954 |
+
|
| 955 |
+
print()
|
| 956 |
+
print('Profiling result for %s lexing %d chars in %.3f ms' %
|
| 957 |
+
(self.__class__.__name__, len(text), sum_total))
|
| 958 |
+
print('=' * 110)
|
| 959 |
+
print('%-20s %-64s ncalls tottime percall' % ('state', 'regex'))
|
| 960 |
+
print('-' * 110)
|
| 961 |
+
for d in data:
|
| 962 |
+
print('%-20s %-65s %5d %8.4f %8.4f' % d)
|
| 963 |
+
print('=' * 110)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/plugin.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.plugin
|
| 3 |
+
~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Pygments plugin interface.
|
| 6 |
+
|
| 7 |
+
lexer plugins::
|
| 8 |
+
|
| 9 |
+
[pygments.lexers]
|
| 10 |
+
yourlexer = yourmodule:YourLexer
|
| 11 |
+
|
| 12 |
+
formatter plugins::
|
| 13 |
+
|
| 14 |
+
[pygments.formatters]
|
| 15 |
+
yourformatter = yourformatter:YourFormatter
|
| 16 |
+
/.ext = yourformatter:YourFormatter
|
| 17 |
+
|
| 18 |
+
As you can see, you can define extensions for the formatter
|
| 19 |
+
with a leading slash.
|
| 20 |
+
|
| 21 |
+
syntax plugins::
|
| 22 |
+
|
| 23 |
+
[pygments.styles]
|
| 24 |
+
yourstyle = yourstyle:YourStyle
|
| 25 |
+
|
| 26 |
+
filter plugin::
|
| 27 |
+
|
| 28 |
+
[pygments.filter]
|
| 29 |
+
yourfilter = yourfilter:YourFilter
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 33 |
+
:license: BSD, see LICENSE for details.
|
| 34 |
+
"""
|
| 35 |
+
import functools
|
| 36 |
+
from importlib.metadata import entry_points
|
| 37 |
+
|
| 38 |
+
LEXER_ENTRY_POINT = 'pygments.lexers'
|
| 39 |
+
FORMATTER_ENTRY_POINT = 'pygments.formatters'
|
| 40 |
+
STYLE_ENTRY_POINT = 'pygments.styles'
|
| 41 |
+
FILTER_ENTRY_POINT = 'pygments.filters'
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
@functools.cache
|
| 45 |
+
def iter_entry_points(group_name):
|
| 46 |
+
groups = entry_points()
|
| 47 |
+
if hasattr(groups, 'select'):
|
| 48 |
+
# New interface in Python 3.10 and newer versions of the
|
| 49 |
+
# importlib_metadata backport.
|
| 50 |
+
return groups.select(group=group_name)
|
| 51 |
+
else:
|
| 52 |
+
# Older interface, deprecated in Python 3.10 and recent
|
| 53 |
+
# importlib_metadata, but we need it in Python 3.8 and 3.9.
|
| 54 |
+
return groups.get(group_name, [])
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def find_plugin_lexers():
|
| 58 |
+
for entrypoint in iter_entry_points(LEXER_ENTRY_POINT):
|
| 59 |
+
yield entrypoint.load()
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def find_plugin_formatters():
|
| 63 |
+
for entrypoint in iter_entry_points(FORMATTER_ENTRY_POINT):
|
| 64 |
+
yield entrypoint.name, entrypoint.load()
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def find_plugin_styles():
|
| 68 |
+
for entrypoint in iter_entry_points(STYLE_ENTRY_POINT):
|
| 69 |
+
yield entrypoint.name, entrypoint.load()
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def find_plugin_filters():
|
| 73 |
+
for entrypoint in iter_entry_points(FILTER_ENTRY_POINT):
|
| 74 |
+
yield entrypoint.name, entrypoint.load()
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/regexopt.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.regexopt
|
| 3 |
+
~~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
An algorithm that generates optimized regexes for matching long lists of
|
| 6 |
+
literal strings.
|
| 7 |
+
|
| 8 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 9 |
+
:license: BSD, see LICENSE for details.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import re
|
| 13 |
+
from re import escape
|
| 14 |
+
from itertools import groupby
|
| 15 |
+
from operator import itemgetter
|
| 16 |
+
|
| 17 |
+
CS_ESCAPE = re.compile(r'[\[\^\\\-\]]')
|
| 18 |
+
FIRST_ELEMENT = itemgetter(0)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def commonprefix(m):
|
| 22 |
+
"""Given an iterable of strings, returns the longest common leading substring"""
|
| 23 |
+
if not m:
|
| 24 |
+
return ""
|
| 25 |
+
s1 = min(m)
|
| 26 |
+
s2 = max(m)
|
| 27 |
+
for i, c in enumerate(s1):
|
| 28 |
+
if c != s2[i]:
|
| 29 |
+
return s1[:i]
|
| 30 |
+
return s1
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
def make_charset(letters):
|
| 34 |
+
return '[' + CS_ESCAPE.sub(lambda m: '\\' + m.group(), ''.join(letters)) + ']'
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def regex_opt_inner(strings, open_paren):
|
| 38 |
+
"""Return a regex that matches any string in the sorted list of strings."""
|
| 39 |
+
close_paren = open_paren and ')' or ''
|
| 40 |
+
# print strings, repr(open_paren)
|
| 41 |
+
if not strings:
|
| 42 |
+
# print '-> nothing left'
|
| 43 |
+
return ''
|
| 44 |
+
first = strings[0]
|
| 45 |
+
if len(strings) == 1:
|
| 46 |
+
# print '-> only 1 string'
|
| 47 |
+
return open_paren + escape(first) + close_paren
|
| 48 |
+
if not first:
|
| 49 |
+
# print '-> first string empty'
|
| 50 |
+
return open_paren + regex_opt_inner(strings[1:], '(?:') \
|
| 51 |
+
+ '?' + close_paren
|
| 52 |
+
if len(first) == 1:
|
| 53 |
+
# multiple one-char strings? make a charset
|
| 54 |
+
oneletter = []
|
| 55 |
+
rest = []
|
| 56 |
+
for s in strings:
|
| 57 |
+
if len(s) == 1:
|
| 58 |
+
oneletter.append(s)
|
| 59 |
+
else:
|
| 60 |
+
rest.append(s)
|
| 61 |
+
if len(oneletter) > 1: # do we have more than one oneletter string?
|
| 62 |
+
if rest:
|
| 63 |
+
# print '-> 1-character + rest'
|
| 64 |
+
return open_paren + regex_opt_inner(rest, '') + '|' \
|
| 65 |
+
+ make_charset(oneletter) + close_paren
|
| 66 |
+
# print '-> only 1-character'
|
| 67 |
+
return open_paren + make_charset(oneletter) + close_paren
|
| 68 |
+
prefix = commonprefix(strings)
|
| 69 |
+
if prefix:
|
| 70 |
+
plen = len(prefix)
|
| 71 |
+
# we have a prefix for all strings
|
| 72 |
+
# print '-> prefix:', prefix
|
| 73 |
+
return open_paren + escape(prefix) \
|
| 74 |
+
+ regex_opt_inner([s[plen:] for s in strings], '(?:') \
|
| 75 |
+
+ close_paren
|
| 76 |
+
# is there a suffix?
|
| 77 |
+
strings_rev = [s[::-1] for s in strings]
|
| 78 |
+
suffix = commonprefix(strings_rev)
|
| 79 |
+
if suffix:
|
| 80 |
+
slen = len(suffix)
|
| 81 |
+
# print '-> suffix:', suffix[::-1]
|
| 82 |
+
return open_paren \
|
| 83 |
+
+ regex_opt_inner(sorted(s[:-slen] for s in strings), '(?:') \
|
| 84 |
+
+ escape(suffix[::-1]) + close_paren
|
| 85 |
+
# recurse on common 1-string prefixes
|
| 86 |
+
# print '-> last resort'
|
| 87 |
+
return open_paren + \
|
| 88 |
+
'|'.join(regex_opt_inner(list(group[1]), '')
|
| 89 |
+
for group in groupby(strings, lambda s: s[0] == first[0])) \
|
| 90 |
+
+ close_paren
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def regex_opt(strings, prefix='', suffix=''):
|
| 94 |
+
"""Return a compiled regex that matches any string in the given list.
|
| 95 |
+
|
| 96 |
+
The strings to match must be literal strings, not regexes. They will be
|
| 97 |
+
regex-escaped.
|
| 98 |
+
|
| 99 |
+
*prefix* and *suffix* are pre- and appended to the final regex.
|
| 100 |
+
"""
|
| 101 |
+
strings = sorted(strings)
|
| 102 |
+
return prefix + regex_opt_inner(strings, '(') + suffix
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/scanner.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.scanner
|
| 3 |
+
~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
This library implements a regex based scanner. Some languages
|
| 6 |
+
like Pascal are easy to parse but have some keywords that
|
| 7 |
+
depend on the context. Because of this it's impossible to lex
|
| 8 |
+
that just by using a regular expression lexer like the
|
| 9 |
+
`RegexLexer`.
|
| 10 |
+
|
| 11 |
+
Have a look at the `DelphiLexer` to get an idea of how to use
|
| 12 |
+
this scanner.
|
| 13 |
+
|
| 14 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 15 |
+
:license: BSD, see LICENSE for details.
|
| 16 |
+
"""
|
| 17 |
+
import re
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class EndOfText(RuntimeError):
|
| 21 |
+
"""
|
| 22 |
+
Raise if end of text is reached and the user
|
| 23 |
+
tried to call a match function.
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class Scanner:
|
| 28 |
+
"""
|
| 29 |
+
Simple scanner
|
| 30 |
+
|
| 31 |
+
All method patterns are regular expression strings (not
|
| 32 |
+
compiled expressions!)
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
def __init__(self, text, flags=0):
|
| 36 |
+
"""
|
| 37 |
+
:param text: The text which should be scanned
|
| 38 |
+
:param flags: default regular expression flags
|
| 39 |
+
"""
|
| 40 |
+
self.data = text
|
| 41 |
+
self.data_length = len(text)
|
| 42 |
+
self.start_pos = 0
|
| 43 |
+
self.pos = 0
|
| 44 |
+
self.flags = flags
|
| 45 |
+
self.last = None
|
| 46 |
+
self.match = None
|
| 47 |
+
self._re_cache = {}
|
| 48 |
+
|
| 49 |
+
def eos(self):
|
| 50 |
+
"""`True` if the scanner reached the end of text."""
|
| 51 |
+
return self.pos >= self.data_length
|
| 52 |
+
eos = property(eos, eos.__doc__)
|
| 53 |
+
|
| 54 |
+
def check(self, pattern):
|
| 55 |
+
"""
|
| 56 |
+
Apply `pattern` on the current position and return
|
| 57 |
+
the match object. (Doesn't touch pos). Use this for
|
| 58 |
+
lookahead.
|
| 59 |
+
"""
|
| 60 |
+
if self.eos:
|
| 61 |
+
raise EndOfText()
|
| 62 |
+
if pattern not in self._re_cache:
|
| 63 |
+
self._re_cache[pattern] = re.compile(pattern, self.flags)
|
| 64 |
+
return self._re_cache[pattern].match(self.data, self.pos)
|
| 65 |
+
|
| 66 |
+
def test(self, pattern):
|
| 67 |
+
"""Apply a pattern on the current position and check
|
| 68 |
+
if it patches. Doesn't touch pos.
|
| 69 |
+
"""
|
| 70 |
+
return self.check(pattern) is not None
|
| 71 |
+
|
| 72 |
+
def scan(self, pattern):
|
| 73 |
+
"""
|
| 74 |
+
Scan the text for the given pattern and update pos/match
|
| 75 |
+
and related fields. The return value is a boolean that
|
| 76 |
+
indicates if the pattern matched. The matched value is
|
| 77 |
+
stored on the instance as ``match``, the last value is
|
| 78 |
+
stored as ``last``. ``start_pos`` is the position of the
|
| 79 |
+
pointer before the pattern was matched, ``pos`` is the
|
| 80 |
+
end position.
|
| 81 |
+
"""
|
| 82 |
+
if self.eos:
|
| 83 |
+
raise EndOfText()
|
| 84 |
+
if pattern not in self._re_cache:
|
| 85 |
+
self._re_cache[pattern] = re.compile(pattern, self.flags)
|
| 86 |
+
self.last = self.match
|
| 87 |
+
m = self._re_cache[pattern].match(self.data, self.pos)
|
| 88 |
+
if m is None:
|
| 89 |
+
return False
|
| 90 |
+
self.start_pos = m.start()
|
| 91 |
+
self.pos = m.end()
|
| 92 |
+
self.match = m.group()
|
| 93 |
+
return True
|
| 94 |
+
|
| 95 |
+
def get_char(self):
|
| 96 |
+
"""Scan exactly one char."""
|
| 97 |
+
self.scan('.')
|
| 98 |
+
|
| 99 |
+
def __repr__(self):
|
| 100 |
+
return '<%s %d/%d>' % (
|
| 101 |
+
self.__class__.__name__,
|
| 102 |
+
self.pos,
|
| 103 |
+
self.data_length
|
| 104 |
+
)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/sphinxext.py
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.sphinxext
|
| 3 |
+
~~~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Sphinx extension to generate automatic documentation of lexers,
|
| 6 |
+
formatters and filters.
|
| 7 |
+
|
| 8 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 9 |
+
:license: BSD, see LICENSE for details.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import sys
|
| 13 |
+
|
| 14 |
+
from docutils import nodes
|
| 15 |
+
from docutils.statemachine import ViewList
|
| 16 |
+
from docutils.parsers.rst import Directive
|
| 17 |
+
from sphinx.util.nodes import nested_parse_with_titles
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
MODULEDOC = '''
|
| 21 |
+
.. module:: %s
|
| 22 |
+
|
| 23 |
+
%s
|
| 24 |
+
%s
|
| 25 |
+
'''
|
| 26 |
+
|
| 27 |
+
LEXERDOC = '''
|
| 28 |
+
.. class:: %s
|
| 29 |
+
|
| 30 |
+
:Short names: %s
|
| 31 |
+
:Filenames: %s
|
| 32 |
+
:MIME types: %s
|
| 33 |
+
|
| 34 |
+
%s
|
| 35 |
+
|
| 36 |
+
%s
|
| 37 |
+
|
| 38 |
+
'''
|
| 39 |
+
|
| 40 |
+
FMTERDOC = '''
|
| 41 |
+
.. class:: %s
|
| 42 |
+
|
| 43 |
+
:Short names: %s
|
| 44 |
+
:Filenames: %s
|
| 45 |
+
|
| 46 |
+
%s
|
| 47 |
+
|
| 48 |
+
'''
|
| 49 |
+
|
| 50 |
+
FILTERDOC = '''
|
| 51 |
+
.. class:: %s
|
| 52 |
+
|
| 53 |
+
:Name: %s
|
| 54 |
+
|
| 55 |
+
%s
|
| 56 |
+
|
| 57 |
+
'''
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class PygmentsDoc(Directive):
|
| 61 |
+
"""
|
| 62 |
+
A directive to collect all lexers/formatters/filters and generate
|
| 63 |
+
autoclass directives for them.
|
| 64 |
+
"""
|
| 65 |
+
has_content = False
|
| 66 |
+
required_arguments = 1
|
| 67 |
+
optional_arguments = 0
|
| 68 |
+
final_argument_whitespace = False
|
| 69 |
+
option_spec = {}
|
| 70 |
+
|
| 71 |
+
def run(self):
|
| 72 |
+
self.filenames = set()
|
| 73 |
+
if self.arguments[0] == 'lexers':
|
| 74 |
+
out = self.document_lexers()
|
| 75 |
+
elif self.arguments[0] == 'formatters':
|
| 76 |
+
out = self.document_formatters()
|
| 77 |
+
elif self.arguments[0] == 'filters':
|
| 78 |
+
out = self.document_filters()
|
| 79 |
+
elif self.arguments[0] == 'lexers_overview':
|
| 80 |
+
out = self.document_lexers_overview()
|
| 81 |
+
else:
|
| 82 |
+
raise Exception('invalid argument for "pygmentsdoc" directive')
|
| 83 |
+
node = nodes.compound()
|
| 84 |
+
vl = ViewList(out.split('\n'), source='')
|
| 85 |
+
nested_parse_with_titles(self.state, vl, node)
|
| 86 |
+
for fn in self.filenames:
|
| 87 |
+
self.state.document.settings.record_dependencies.add(fn)
|
| 88 |
+
return node.children
|
| 89 |
+
|
| 90 |
+
def document_lexers_overview(self):
|
| 91 |
+
"""Generate a tabular overview of all lexers.
|
| 92 |
+
|
| 93 |
+
The columns are the lexer name, the extensions handled by this lexer
|
| 94 |
+
(or "None"), the aliases and a link to the lexer class."""
|
| 95 |
+
from pygments.lexers._mapping import LEXERS
|
| 96 |
+
import pygments.lexers
|
| 97 |
+
out = []
|
| 98 |
+
|
| 99 |
+
table = []
|
| 100 |
+
|
| 101 |
+
def format_link(name, url):
|
| 102 |
+
if url:
|
| 103 |
+
return f'`{name} <{url}>`_'
|
| 104 |
+
return name
|
| 105 |
+
|
| 106 |
+
for classname, data in sorted(LEXERS.items(), key=lambda x: x[1][1].lower()):
|
| 107 |
+
lexer_cls = pygments.lexers.find_lexer_class(data[1])
|
| 108 |
+
extensions = lexer_cls.filenames + lexer_cls.alias_filenames
|
| 109 |
+
|
| 110 |
+
table.append({
|
| 111 |
+
'name': format_link(data[1], lexer_cls.url),
|
| 112 |
+
'extensions': ', '.join(extensions).replace('*', '\\*').replace('_', '\\') or 'None',
|
| 113 |
+
'aliases': ', '.join(data[2]),
|
| 114 |
+
'class': f'{data[0]}.{classname}'
|
| 115 |
+
})
|
| 116 |
+
|
| 117 |
+
column_names = ['name', 'extensions', 'aliases', 'class']
|
| 118 |
+
column_lengths = [max([len(row[column]) for row in table if row[column]])
|
| 119 |
+
for column in column_names]
|
| 120 |
+
|
| 121 |
+
def write_row(*columns):
|
| 122 |
+
"""Format a table row"""
|
| 123 |
+
out = []
|
| 124 |
+
for length, col in zip(column_lengths, columns):
|
| 125 |
+
if col:
|
| 126 |
+
out.append(col.ljust(length))
|
| 127 |
+
else:
|
| 128 |
+
out.append(' '*length)
|
| 129 |
+
|
| 130 |
+
return ' '.join(out)
|
| 131 |
+
|
| 132 |
+
def write_seperator():
|
| 133 |
+
"""Write a table separator row"""
|
| 134 |
+
sep = ['='*c for c in column_lengths]
|
| 135 |
+
return write_row(*sep)
|
| 136 |
+
|
| 137 |
+
out.append(write_seperator())
|
| 138 |
+
out.append(write_row('Name', 'Extension(s)', 'Short name(s)', 'Lexer class'))
|
| 139 |
+
out.append(write_seperator())
|
| 140 |
+
for row in table:
|
| 141 |
+
out.append(write_row(
|
| 142 |
+
row['name'],
|
| 143 |
+
row['extensions'],
|
| 144 |
+
row['aliases'],
|
| 145 |
+
f':class:`~{row["class"]}`'))
|
| 146 |
+
out.append(write_seperator())
|
| 147 |
+
|
| 148 |
+
return '\n'.join(out)
|
| 149 |
+
|
| 150 |
+
def document_lexers(self):
|
| 151 |
+
from pygments.lexers._mapping import LEXERS
|
| 152 |
+
import pygments
|
| 153 |
+
import inspect
|
| 154 |
+
import pathlib
|
| 155 |
+
|
| 156 |
+
out = []
|
| 157 |
+
modules = {}
|
| 158 |
+
moduledocstrings = {}
|
| 159 |
+
for classname, data in sorted(LEXERS.items(), key=lambda x: x[0]):
|
| 160 |
+
module = data[0]
|
| 161 |
+
mod = __import__(module, None, None, [classname])
|
| 162 |
+
self.filenames.add(mod.__file__)
|
| 163 |
+
cls = getattr(mod, classname)
|
| 164 |
+
if not cls.__doc__:
|
| 165 |
+
print(f"Warning: {classname} does not have a docstring.")
|
| 166 |
+
docstring = cls.__doc__
|
| 167 |
+
if isinstance(docstring, bytes):
|
| 168 |
+
docstring = docstring.decode('utf8')
|
| 169 |
+
|
| 170 |
+
example_file = getattr(cls, '_example', None)
|
| 171 |
+
if example_file:
|
| 172 |
+
p = pathlib.Path(inspect.getabsfile(pygments)).parent.parent /\
|
| 173 |
+
'tests' / 'examplefiles' / example_file
|
| 174 |
+
content = p.read_text(encoding='utf-8')
|
| 175 |
+
if not content:
|
| 176 |
+
raise Exception(
|
| 177 |
+
f"Empty example file '{example_file}' for lexer "
|
| 178 |
+
f"{classname}")
|
| 179 |
+
|
| 180 |
+
if data[2]:
|
| 181 |
+
lexer_name = data[2][0]
|
| 182 |
+
docstring += '\n\n .. admonition:: Example\n'
|
| 183 |
+
docstring += f'\n .. code-block:: {lexer_name}\n\n'
|
| 184 |
+
for line in content.splitlines():
|
| 185 |
+
docstring += f' {line}\n'
|
| 186 |
+
|
| 187 |
+
if cls.version_added:
|
| 188 |
+
version_line = f'.. versionadded:: {cls.version_added}'
|
| 189 |
+
else:
|
| 190 |
+
version_line = ''
|
| 191 |
+
|
| 192 |
+
modules.setdefault(module, []).append((
|
| 193 |
+
classname,
|
| 194 |
+
', '.join(data[2]) or 'None',
|
| 195 |
+
', '.join(data[3]).replace('*', '\\*').replace('_', '\\') or 'None',
|
| 196 |
+
', '.join(data[4]) or 'None',
|
| 197 |
+
docstring,
|
| 198 |
+
version_line))
|
| 199 |
+
if module not in moduledocstrings:
|
| 200 |
+
moddoc = mod.__doc__
|
| 201 |
+
if isinstance(moddoc, bytes):
|
| 202 |
+
moddoc = moddoc.decode('utf8')
|
| 203 |
+
moduledocstrings[module] = moddoc
|
| 204 |
+
|
| 205 |
+
for module, lexers in sorted(modules.items(), key=lambda x: x[0]):
|
| 206 |
+
if moduledocstrings[module] is None:
|
| 207 |
+
raise Exception(f"Missing docstring for {module}")
|
| 208 |
+
heading = moduledocstrings[module].splitlines()[4].strip().rstrip('.')
|
| 209 |
+
out.append(MODULEDOC % (module, heading, '-'*len(heading)))
|
| 210 |
+
for data in lexers:
|
| 211 |
+
out.append(LEXERDOC % data)
|
| 212 |
+
|
| 213 |
+
return ''.join(out)
|
| 214 |
+
|
| 215 |
+
def document_formatters(self):
|
| 216 |
+
from pygments.formatters import FORMATTERS
|
| 217 |
+
|
| 218 |
+
out = []
|
| 219 |
+
for classname, data in sorted(FORMATTERS.items(), key=lambda x: x[0]):
|
| 220 |
+
module = data[0]
|
| 221 |
+
mod = __import__(module, None, None, [classname])
|
| 222 |
+
self.filenames.add(mod.__file__)
|
| 223 |
+
cls = getattr(mod, classname)
|
| 224 |
+
docstring = cls.__doc__
|
| 225 |
+
if isinstance(docstring, bytes):
|
| 226 |
+
docstring = docstring.decode('utf8')
|
| 227 |
+
heading = cls.__name__
|
| 228 |
+
out.append(FMTERDOC % (heading, ', '.join(data[2]) or 'None',
|
| 229 |
+
', '.join(data[3]).replace('*', '\\*') or 'None',
|
| 230 |
+
docstring))
|
| 231 |
+
return ''.join(out)
|
| 232 |
+
|
| 233 |
+
def document_filters(self):
|
| 234 |
+
from pygments.filters import FILTERS
|
| 235 |
+
|
| 236 |
+
out = []
|
| 237 |
+
for name, cls in FILTERS.items():
|
| 238 |
+
self.filenames.add(sys.modules[cls.__module__].__file__)
|
| 239 |
+
docstring = cls.__doc__
|
| 240 |
+
if isinstance(docstring, bytes):
|
| 241 |
+
docstring = docstring.decode('utf8')
|
| 242 |
+
out.append(FILTERDOC % (cls.__name__, name, docstring))
|
| 243 |
+
return ''.join(out)
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
def setup(app):
|
| 247 |
+
app.add_directive('pygmentsdoc', PygmentsDoc)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/style.py
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.style
|
| 3 |
+
~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Basic style object.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
from pygments.token import Token, STANDARD_TYPES
|
| 12 |
+
|
| 13 |
+
# Default mapping of ansixxx to RGB colors.
|
| 14 |
+
_ansimap = {
|
| 15 |
+
# dark
|
| 16 |
+
'ansiblack': '000000',
|
| 17 |
+
'ansired': '7f0000',
|
| 18 |
+
'ansigreen': '007f00',
|
| 19 |
+
'ansiyellow': '7f7fe0',
|
| 20 |
+
'ansiblue': '00007f',
|
| 21 |
+
'ansimagenta': '7f007f',
|
| 22 |
+
'ansicyan': '007f7f',
|
| 23 |
+
'ansigray': 'e5e5e5',
|
| 24 |
+
# normal
|
| 25 |
+
'ansibrightblack': '555555',
|
| 26 |
+
'ansibrightred': 'ff0000',
|
| 27 |
+
'ansibrightgreen': '00ff00',
|
| 28 |
+
'ansibrightyellow': 'ffff00',
|
| 29 |
+
'ansibrightblue': '0000ff',
|
| 30 |
+
'ansibrightmagenta': 'ff00ff',
|
| 31 |
+
'ansibrightcyan': '00ffff',
|
| 32 |
+
'ansiwhite': 'ffffff',
|
| 33 |
+
}
|
| 34 |
+
# mapping of deprecated #ansixxx colors to new color names
|
| 35 |
+
_deprecated_ansicolors = {
|
| 36 |
+
# dark
|
| 37 |
+
'#ansiblack': 'ansiblack',
|
| 38 |
+
'#ansidarkred': 'ansired',
|
| 39 |
+
'#ansidarkgreen': 'ansigreen',
|
| 40 |
+
'#ansibrown': 'ansiyellow',
|
| 41 |
+
'#ansidarkblue': 'ansiblue',
|
| 42 |
+
'#ansipurple': 'ansimagenta',
|
| 43 |
+
'#ansiteal': 'ansicyan',
|
| 44 |
+
'#ansilightgray': 'ansigray',
|
| 45 |
+
# normal
|
| 46 |
+
'#ansidarkgray': 'ansibrightblack',
|
| 47 |
+
'#ansired': 'ansibrightred',
|
| 48 |
+
'#ansigreen': 'ansibrightgreen',
|
| 49 |
+
'#ansiyellow': 'ansibrightyellow',
|
| 50 |
+
'#ansiblue': 'ansibrightblue',
|
| 51 |
+
'#ansifuchsia': 'ansibrightmagenta',
|
| 52 |
+
'#ansiturquoise': 'ansibrightcyan',
|
| 53 |
+
'#ansiwhite': 'ansiwhite',
|
| 54 |
+
}
|
| 55 |
+
ansicolors = set(_ansimap)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
class StyleMeta(type):
|
| 59 |
+
|
| 60 |
+
def __new__(mcs, name, bases, dct):
|
| 61 |
+
obj = type.__new__(mcs, name, bases, dct)
|
| 62 |
+
for token in STANDARD_TYPES:
|
| 63 |
+
if token not in obj.styles:
|
| 64 |
+
obj.styles[token] = ''
|
| 65 |
+
|
| 66 |
+
def colorformat(text):
|
| 67 |
+
if text in ansicolors:
|
| 68 |
+
return text
|
| 69 |
+
if text[0:1] == '#':
|
| 70 |
+
col = text[1:]
|
| 71 |
+
if len(col) == 6:
|
| 72 |
+
return col
|
| 73 |
+
elif len(col) == 3:
|
| 74 |
+
return col[0] * 2 + col[1] * 2 + col[2] * 2
|
| 75 |
+
elif text == '':
|
| 76 |
+
return ''
|
| 77 |
+
elif text.startswith('var') or text.startswith('calc'):
|
| 78 |
+
return text
|
| 79 |
+
assert False, f"wrong color format {text!r}"
|
| 80 |
+
|
| 81 |
+
_styles = obj._styles = {}
|
| 82 |
+
|
| 83 |
+
for ttype in obj.styles:
|
| 84 |
+
for token in ttype.split():
|
| 85 |
+
if token in _styles:
|
| 86 |
+
continue
|
| 87 |
+
ndef = _styles.get(token.parent, None)
|
| 88 |
+
styledefs = obj.styles.get(token, '').split()
|
| 89 |
+
if not ndef or token is None:
|
| 90 |
+
ndef = ['', 0, 0, 0, '', '', 0, 0, 0]
|
| 91 |
+
elif 'noinherit' in styledefs and token is not Token:
|
| 92 |
+
ndef = _styles[Token][:]
|
| 93 |
+
else:
|
| 94 |
+
ndef = ndef[:]
|
| 95 |
+
_styles[token] = ndef
|
| 96 |
+
for styledef in obj.styles.get(token, '').split():
|
| 97 |
+
if styledef == 'noinherit':
|
| 98 |
+
pass
|
| 99 |
+
elif styledef == 'bold':
|
| 100 |
+
ndef[1] = 1
|
| 101 |
+
elif styledef == 'nobold':
|
| 102 |
+
ndef[1] = 0
|
| 103 |
+
elif styledef == 'italic':
|
| 104 |
+
ndef[2] = 1
|
| 105 |
+
elif styledef == 'noitalic':
|
| 106 |
+
ndef[2] = 0
|
| 107 |
+
elif styledef == 'underline':
|
| 108 |
+
ndef[3] = 1
|
| 109 |
+
elif styledef == 'nounderline':
|
| 110 |
+
ndef[3] = 0
|
| 111 |
+
elif styledef[:3] == 'bg:':
|
| 112 |
+
ndef[4] = colorformat(styledef[3:])
|
| 113 |
+
elif styledef[:7] == 'border:':
|
| 114 |
+
ndef[5] = colorformat(styledef[7:])
|
| 115 |
+
elif styledef == 'roman':
|
| 116 |
+
ndef[6] = 1
|
| 117 |
+
elif styledef == 'sans':
|
| 118 |
+
ndef[7] = 1
|
| 119 |
+
elif styledef == 'mono':
|
| 120 |
+
ndef[8] = 1
|
| 121 |
+
else:
|
| 122 |
+
ndef[0] = colorformat(styledef)
|
| 123 |
+
|
| 124 |
+
return obj
|
| 125 |
+
|
| 126 |
+
def style_for_token(cls, token):
|
| 127 |
+
t = cls._styles[token]
|
| 128 |
+
ansicolor = bgansicolor = None
|
| 129 |
+
color = t[0]
|
| 130 |
+
if color in _deprecated_ansicolors:
|
| 131 |
+
color = _deprecated_ansicolors[color]
|
| 132 |
+
if color in ansicolors:
|
| 133 |
+
ansicolor = color
|
| 134 |
+
color = _ansimap[color]
|
| 135 |
+
bgcolor = t[4]
|
| 136 |
+
if bgcolor in _deprecated_ansicolors:
|
| 137 |
+
bgcolor = _deprecated_ansicolors[bgcolor]
|
| 138 |
+
if bgcolor in ansicolors:
|
| 139 |
+
bgansicolor = bgcolor
|
| 140 |
+
bgcolor = _ansimap[bgcolor]
|
| 141 |
+
|
| 142 |
+
return {
|
| 143 |
+
'color': color or None,
|
| 144 |
+
'bold': bool(t[1]),
|
| 145 |
+
'italic': bool(t[2]),
|
| 146 |
+
'underline': bool(t[3]),
|
| 147 |
+
'bgcolor': bgcolor or None,
|
| 148 |
+
'border': t[5] or None,
|
| 149 |
+
'roman': bool(t[6]) or None,
|
| 150 |
+
'sans': bool(t[7]) or None,
|
| 151 |
+
'mono': bool(t[8]) or None,
|
| 152 |
+
'ansicolor': ansicolor,
|
| 153 |
+
'bgansicolor': bgansicolor,
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
def list_styles(cls):
|
| 157 |
+
return list(cls)
|
| 158 |
+
|
| 159 |
+
def styles_token(cls, ttype):
|
| 160 |
+
return ttype in cls._styles
|
| 161 |
+
|
| 162 |
+
def __iter__(cls):
|
| 163 |
+
for token in cls._styles:
|
| 164 |
+
yield token, cls.style_for_token(token)
|
| 165 |
+
|
| 166 |
+
def __len__(cls):
|
| 167 |
+
return len(cls._styles)
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
class Style(metaclass=StyleMeta):
|
| 171 |
+
|
| 172 |
+
#: overall background color (``None`` means transparent)
|
| 173 |
+
background_color = '#ffffff'
|
| 174 |
+
|
| 175 |
+
#: highlight background color
|
| 176 |
+
highlight_color = '#ffffcc'
|
| 177 |
+
|
| 178 |
+
#: line number font color
|
| 179 |
+
line_number_color = 'inherit'
|
| 180 |
+
|
| 181 |
+
#: line number background color
|
| 182 |
+
line_number_background_color = 'transparent'
|
| 183 |
+
|
| 184 |
+
#: special line number font color
|
| 185 |
+
line_number_special_color = '#000000'
|
| 186 |
+
|
| 187 |
+
#: special line number background color
|
| 188 |
+
line_number_special_background_color = '#ffffc0'
|
| 189 |
+
|
| 190 |
+
#: Style definitions for individual token types.
|
| 191 |
+
styles = {}
|
| 192 |
+
|
| 193 |
+
#: user-friendly style name (used when selecting the style, so this
|
| 194 |
+
# should be all-lowercase, no spaces, hyphens)
|
| 195 |
+
name = 'unnamed'
|
| 196 |
+
|
| 197 |
+
aliases = []
|
| 198 |
+
|
| 199 |
+
# Attribute for lexers defined within Pygments. If set
|
| 200 |
+
# to True, the style is not shown in the style gallery
|
| 201 |
+
# on the website. This is intended for language-specific
|
| 202 |
+
# styles.
|
| 203 |
+
web_style_gallery_exclude = False
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/token.py
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.token
|
| 3 |
+
~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Basic token types and the standard tokens.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class _TokenType(tuple):
|
| 13 |
+
parent = None
|
| 14 |
+
|
| 15 |
+
def split(self):
|
| 16 |
+
buf = []
|
| 17 |
+
node = self
|
| 18 |
+
while node is not None:
|
| 19 |
+
buf.append(node)
|
| 20 |
+
node = node.parent
|
| 21 |
+
buf.reverse()
|
| 22 |
+
return buf
|
| 23 |
+
|
| 24 |
+
def __init__(self, *args):
|
| 25 |
+
# no need to call super.__init__
|
| 26 |
+
self.subtypes = set()
|
| 27 |
+
|
| 28 |
+
def __contains__(self, val):
|
| 29 |
+
return self is val or (
|
| 30 |
+
type(val) is self.__class__ and
|
| 31 |
+
val[:len(self)] == self
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
def __getattr__(self, val):
|
| 35 |
+
if not val or not val[0].isupper():
|
| 36 |
+
return tuple.__getattribute__(self, val)
|
| 37 |
+
new = _TokenType(self + (val,))
|
| 38 |
+
setattr(self, val, new)
|
| 39 |
+
self.subtypes.add(new)
|
| 40 |
+
new.parent = self
|
| 41 |
+
return new
|
| 42 |
+
|
| 43 |
+
def __repr__(self):
|
| 44 |
+
return 'Token' + (self and '.' or '') + '.'.join(self)
|
| 45 |
+
|
| 46 |
+
def __copy__(self):
|
| 47 |
+
# These instances are supposed to be singletons
|
| 48 |
+
return self
|
| 49 |
+
|
| 50 |
+
def __deepcopy__(self, memo):
|
| 51 |
+
# These instances are supposed to be singletons
|
| 52 |
+
return self
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
Token = _TokenType()
|
| 56 |
+
|
| 57 |
+
# Special token types
|
| 58 |
+
Text = Token.Text
|
| 59 |
+
Whitespace = Text.Whitespace
|
| 60 |
+
Escape = Token.Escape
|
| 61 |
+
Error = Token.Error
|
| 62 |
+
# Text that doesn't belong to this lexer (e.g. HTML in PHP)
|
| 63 |
+
Other = Token.Other
|
| 64 |
+
|
| 65 |
+
# Common token types for source code
|
| 66 |
+
Keyword = Token.Keyword
|
| 67 |
+
Name = Token.Name
|
| 68 |
+
Literal = Token.Literal
|
| 69 |
+
String = Literal.String
|
| 70 |
+
Number = Literal.Number
|
| 71 |
+
Punctuation = Token.Punctuation
|
| 72 |
+
Operator = Token.Operator
|
| 73 |
+
Comment = Token.Comment
|
| 74 |
+
|
| 75 |
+
# Generic types for non-source code
|
| 76 |
+
Generic = Token.Generic
|
| 77 |
+
|
| 78 |
+
# String and some others are not direct children of Token.
|
| 79 |
+
# alias them:
|
| 80 |
+
Token.Token = Token
|
| 81 |
+
Token.String = String
|
| 82 |
+
Token.Number = Number
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def is_token_subtype(ttype, other):
|
| 86 |
+
"""
|
| 87 |
+
Return True if ``ttype`` is a subtype of ``other``.
|
| 88 |
+
|
| 89 |
+
exists for backwards compatibility. use ``ttype in other`` now.
|
| 90 |
+
"""
|
| 91 |
+
return ttype in other
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def string_to_tokentype(s):
|
| 95 |
+
"""
|
| 96 |
+
Convert a string into a token type::
|
| 97 |
+
|
| 98 |
+
>>> string_to_token('String.Double')
|
| 99 |
+
Token.Literal.String.Double
|
| 100 |
+
>>> string_to_token('Token.Literal.Number')
|
| 101 |
+
Token.Literal.Number
|
| 102 |
+
>>> string_to_token('')
|
| 103 |
+
Token
|
| 104 |
+
|
| 105 |
+
Tokens that are already tokens are returned unchanged:
|
| 106 |
+
|
| 107 |
+
>>> string_to_token(String)
|
| 108 |
+
Token.Literal.String
|
| 109 |
+
"""
|
| 110 |
+
if isinstance(s, _TokenType):
|
| 111 |
+
return s
|
| 112 |
+
if not s:
|
| 113 |
+
return Token
|
| 114 |
+
node = Token
|
| 115 |
+
for item in s.split('.'):
|
| 116 |
+
node = getattr(node, item)
|
| 117 |
+
return node
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
# Map standard token types to short names, used in CSS class naming.
|
| 121 |
+
# If you add a new item, please be sure to run this file to perform
|
| 122 |
+
# a consistency check for duplicate values.
|
| 123 |
+
STANDARD_TYPES = {
|
| 124 |
+
Token: '',
|
| 125 |
+
|
| 126 |
+
Text: '',
|
| 127 |
+
Whitespace: 'w',
|
| 128 |
+
Escape: 'esc',
|
| 129 |
+
Error: 'err',
|
| 130 |
+
Other: 'x',
|
| 131 |
+
|
| 132 |
+
Keyword: 'k',
|
| 133 |
+
Keyword.Constant: 'kc',
|
| 134 |
+
Keyword.Declaration: 'kd',
|
| 135 |
+
Keyword.Namespace: 'kn',
|
| 136 |
+
Keyword.Pseudo: 'kp',
|
| 137 |
+
Keyword.Reserved: 'kr',
|
| 138 |
+
Keyword.Type: 'kt',
|
| 139 |
+
|
| 140 |
+
Name: 'n',
|
| 141 |
+
Name.Attribute: 'na',
|
| 142 |
+
Name.Builtin: 'nb',
|
| 143 |
+
Name.Builtin.Pseudo: 'bp',
|
| 144 |
+
Name.Class: 'nc',
|
| 145 |
+
Name.Constant: 'no',
|
| 146 |
+
Name.Decorator: 'nd',
|
| 147 |
+
Name.Entity: 'ni',
|
| 148 |
+
Name.Exception: 'ne',
|
| 149 |
+
Name.Function: 'nf',
|
| 150 |
+
Name.Function.Magic: 'fm',
|
| 151 |
+
Name.Property: 'py',
|
| 152 |
+
Name.Label: 'nl',
|
| 153 |
+
Name.Namespace: 'nn',
|
| 154 |
+
Name.Other: 'nx',
|
| 155 |
+
Name.Tag: 'nt',
|
| 156 |
+
Name.Variable: 'nv',
|
| 157 |
+
Name.Variable.Class: 'vc',
|
| 158 |
+
Name.Variable.Global: 'vg',
|
| 159 |
+
Name.Variable.Instance: 'vi',
|
| 160 |
+
Name.Variable.Magic: 'vm',
|
| 161 |
+
|
| 162 |
+
Literal: 'l',
|
| 163 |
+
Literal.Date: 'ld',
|
| 164 |
+
|
| 165 |
+
String: 's',
|
| 166 |
+
String.Affix: 'sa',
|
| 167 |
+
String.Backtick: 'sb',
|
| 168 |
+
String.Char: 'sc',
|
| 169 |
+
String.Delimiter: 'dl',
|
| 170 |
+
String.Doc: 'sd',
|
| 171 |
+
String.Double: 's2',
|
| 172 |
+
String.Escape: 'se',
|
| 173 |
+
String.Heredoc: 'sh',
|
| 174 |
+
String.Interpol: 'si',
|
| 175 |
+
String.Other: 'sx',
|
| 176 |
+
String.Regex: 'sr',
|
| 177 |
+
String.Single: 's1',
|
| 178 |
+
String.Symbol: 'ss',
|
| 179 |
+
|
| 180 |
+
Number: 'm',
|
| 181 |
+
Number.Bin: 'mb',
|
| 182 |
+
Number.Float: 'mf',
|
| 183 |
+
Number.Hex: 'mh',
|
| 184 |
+
Number.Integer: 'mi',
|
| 185 |
+
Number.Integer.Long: 'il',
|
| 186 |
+
Number.Oct: 'mo',
|
| 187 |
+
|
| 188 |
+
Operator: 'o',
|
| 189 |
+
Operator.Word: 'ow',
|
| 190 |
+
|
| 191 |
+
Punctuation: 'p',
|
| 192 |
+
Punctuation.Marker: 'pm',
|
| 193 |
+
|
| 194 |
+
Comment: 'c',
|
| 195 |
+
Comment.Hashbang: 'ch',
|
| 196 |
+
Comment.Multiline: 'cm',
|
| 197 |
+
Comment.Preproc: 'cp',
|
| 198 |
+
Comment.PreprocFile: 'cpf',
|
| 199 |
+
Comment.Single: 'c1',
|
| 200 |
+
Comment.Special: 'cs',
|
| 201 |
+
|
| 202 |
+
Generic: 'g',
|
| 203 |
+
Generic.Deleted: 'gd',
|
| 204 |
+
Generic.Emph: 'ge',
|
| 205 |
+
Generic.Error: 'gr',
|
| 206 |
+
Generic.Heading: 'gh',
|
| 207 |
+
Generic.Inserted: 'gi',
|
| 208 |
+
Generic.Output: 'go',
|
| 209 |
+
Generic.Prompt: 'gp',
|
| 210 |
+
Generic.Strong: 'gs',
|
| 211 |
+
Generic.Subheading: 'gu',
|
| 212 |
+
Generic.EmphStrong: 'ges',
|
| 213 |
+
Generic.Traceback: 'gt',
|
| 214 |
+
}
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/unistring.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.unistring
|
| 3 |
+
~~~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Strings of all Unicode characters of a certain category.
|
| 6 |
+
Used for matching in Unicode-aware languages. Run to regenerate.
|
| 7 |
+
|
| 8 |
+
Inspired by chartypes_create.py from the MoinMoin project.
|
| 9 |
+
|
| 10 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 11 |
+
:license: BSD, see LICENSE for details.
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
Cc = '\x00-\x1f\x7f-\x9f'
|
| 15 |
+
|
| 16 |
+
Cf = '\xad\u0600-\u0605\u061c\u06dd\u070f\u08e2\u180e\u200b-\u200f\u202a-\u202e\u2060-\u2064\u2066-\u206f\ufeff\ufff9-\ufffb\U000110bd\U000110cd\U0001bca0-\U0001bca3\U0001d173-\U0001d17a\U000e0001\U000e0020-\U000e007f'
|
| 17 |
+
|
| 18 |
+
Cn = '\u0378-\u0379\u0380-\u0383\u038b\u038d\u03a2\u0530\u0557-\u0558\u058b-\u058c\u0590\u05c8-\u05cf\u05eb-\u05ee\u05f5-\u05ff\u061d\u070e\u074b-\u074c\u07b2-\u07bf\u07fb-\u07fc\u082e-\u082f\u083f\u085c-\u085d\u085f\u086b-\u089f\u08b5\u08be-\u08d2\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09bb\u09c5-\u09c6\u09c9-\u09ca\u09cf-\u09d6\u09d8-\u09db\u09de\u09e4-\u09e5\u09ff-\u0a00\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a3b\u0a3d\u0a43-\u0a46\u0a49-\u0a4a\u0a4e-\u0a50\u0a52-\u0a58\u0a5d\u0a5f-\u0a65\u0a77-\u0a80\u0a84\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abb\u0ac6\u0aca\u0ace-\u0acf\u0ad1-\u0adf\u0ae4-\u0ae5\u0af2-\u0af8\u0b00\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34\u0b3a-\u0b3b\u0b45-\u0b46\u0b49-\u0b4a\u0b4e-\u0b55\u0b58-\u0b5b\u0b5e\u0b64-\u0b65\u0b78-\u0b81\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bba-\u0bbd\u0bc3-\u0bc5\u0bc9\u0bce-\u0bcf\u0bd1-\u0bd6\u0bd8-\u0be5\u0bfb-\u0bff\u0c0d\u0c11\u0c29\u0c3a-\u0c3c\u0c45\u0c49\u0c4e-\u0c54\u0c57\u0c5b-\u0c5f\u0c64-\u0c65\u0c70-\u0c77\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cbb\u0cc5\u0cc9\u0cce-\u0cd4\u0cd7-\u0cdd\u0cdf\u0ce4-\u0ce5\u0cf0\u0cf3-\u0cff\u0d04\u0d0d\u0d11\u0d45\u0d49\u0d50-\u0d53\u0d64-\u0d65\u0d80-\u0d81\u0d84\u0d97-\u0d99\u0db2\u0dbc\u0dbe-\u0dbf\u0dc7-\u0dc9\u0dcb-\u0dce\u0dd5\u0dd7\u0de0-\u0de5\u0df0-\u0df1\u0df5-\u0e00\u0e3b-\u0e3e\u0e5c-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eba\u0ebe-\u0ebf\u0ec5\u0ec7\u0ece-\u0ecf\u0eda-\u0edb\u0ee0-\u0eff\u0f48\u0f6d-\u0f70\u0f98\u0fbd\u0fcd\u0fdb-\u0fff\u10c6\u10c8-\u10cc\u10ce-\u10cf\u1249\u124e-\u124f\u1257\u1259\u125e-\u125f\u1289\u128e-\u128f\u12b1\u12b6-\u12b7\u12bf\u12c1\u12c6-\u12c7\u12d7\u1311\u1316-\u1317\u135b-\u135c\u137d-\u137f\u139a-\u139f\u13f6-\u13f7\u13fe-\u13ff\u169d-\u169f\u16f9-\u16ff\u170d\u1715-\u171f\u1737-\u173f\u1754-\u175f\u176d\u1771\u1774-\u177f\u17de-\u17df\u17ea-\u17ef\u17fa-\u17ff\u180f\u181a-\u181f\u1879-\u187f\u18ab-\u18af\u18f6-\u18ff\u191f\u192c-\u192f\u193c-\u193f\u1941-\u1943\u196e-\u196f\u1975-\u197f\u19ac-\u19af\u19ca-\u19cf\u19db-\u19dd\u1a1c-\u1a1d\u1a5f\u1a7d-\u1a7e\u1a8a-\u1a8f\u1a9a-\u1a9f\u1aae-\u1aaf\u1abf-\u1aff\u1b4c-\u1b4f\u1b7d-\u1b7f\u1bf4-\u1bfb\u1c38-\u1c3a\u1c4a-\u1c4c\u1c89-\u1c8f\u1cbb-\u1cbc\u1cc8-\u1ccf\u1cfa-\u1cff\u1dfa\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fc5\u1fd4-\u1fd5\u1fdc\u1ff0-\u1ff1\u1ff5\u1fff\u2065\u2072-\u2073\u208f\u209d-\u209f\u20c0-\u20cf\u20f1-\u20ff\u218c-\u218f\u2427-\u243f\u244b-\u245f\u2b74-\u2b75\u2b96-\u2b97\u2bc9\u2bff\u2c2f\u2c5f\u2cf4-\u2cf8\u2d26\u2d28-\u2d2c\u2d2e-\u2d2f\u2d68-\u2d6e\u2d71-\u2d7e\u2d97-\u2d9f\u2da7\u2daf\u2db7\u2dbf\u2dc7\u2dcf\u2dd7\u2ddf\u2e4f-\u2e7f\u2e9a\u2ef4-\u2eff\u2fd6-\u2fef\u2ffc-\u2fff\u3040\u3097-\u3098\u3100-\u3104\u3130\u318f\u31bb-\u31bf\u31e4-\u31ef\u321f\u32ff\u4db6-\u4dbf\u9ff0-\u9fff\ua48d-\ua48f\ua4c7-\ua4cf\ua62c-\ua63f\ua6f8-\ua6ff\ua7ba-\ua7f6\ua82c-\ua82f\ua83a-\ua83f\ua878-\ua87f\ua8c6-\ua8cd\ua8da-\ua8df\ua954-\ua95e\ua97d-\ua97f\ua9ce\ua9da-\ua9dd\ua9ff\uaa37-\uaa3f\uaa4e-\uaa4f\uaa5a-\uaa5b\uaac3-\uaada\uaaf7-\uab00\uab07-\uab08\uab0f-\uab10\uab17-\uab1f\uab27\uab2f\uab66-\uab6f\uabee-\uabef\uabfa-\uabff\ud7a4-\ud7af\ud7c7-\ud7ca\ud7fc-\ud7ff\ufa6e-\ufa6f\ufada-\ufaff\ufb07-\ufb12\ufb18-\ufb1c\ufb37\ufb3d\ufb3f\ufb42\ufb45\ufbc2-\ufbd2\ufd40-\ufd4f\ufd90-\ufd91\ufdc8-\ufdef\ufdfe-\ufdff\ufe1a-\ufe1f\ufe53\ufe67\ufe6c-\ufe6f\ufe75\ufefd-\ufefe\uff00\uffbf-\uffc1\uffc8-\uffc9\uffd0-\uffd1\uffd8-\uffd9\uffdd-\uffdf\uffe7\uffef-\ufff8\ufffe-\uffff\U0001000c\U00010027\U0001003b\U0001003e\U0001004e-\U0001004f\U0001005e-\U0001007f\U000100fb-\U000100ff\U00010103-\U00010106\U00010134-\U00010136\U0001018f\U0001019c-\U0001019f\U000101a1-\U000101cf\U000101fe-\U0001027f\U0001029d-\U0001029f\U000102d1-\U000102df\U000102fc-\U000102ff\U00010324-\U0001032c\U0001034b-\U0001034f\U0001037b-\U0001037f\U0001039e\U000103c4-\U000103c7\U000103d6-\U000103ff\U0001049e-\U0001049f\U000104aa-\U000104af\U000104d4-\U000104d7\U000104fc-\U000104ff\U00010528-\U0001052f\U00010564-\U0001056e\U00010570-\U000105ff\U00010737-\U0001073f\U00010756-\U0001075f\U00010768-\U000107ff\U00010806-\U00010807\U00010809\U00010836\U00010839-\U0001083b\U0001083d-\U0001083e\U00010856\U0001089f-\U000108a6\U000108b0-\U000108df\U000108f3\U000108f6-\U000108fa\U0001091c-\U0001091e\U0001093a-\U0001093e\U00010940-\U0001097f\U000109b8-\U000109bb\U000109d0-\U000109d1\U00010a04\U00010a07-\U00010a0b\U00010a14\U00010a18\U00010a36-\U00010a37\U00010a3b-\U00010a3e\U00010a49-\U00010a4f\U00010a59-\U00010a5f\U00010aa0-\U00010abf\U00010ae7-\U00010aea\U00010af7-\U00010aff\U00010b36-\U00010b38\U00010b56-\U00010b57\U00010b73-\U00010b77\U00010b92-\U00010b98\U00010b9d-\U00010ba8\U00010bb0-\U00010bff\U00010c49-\U00010c7f\U00010cb3-\U00010cbf\U00010cf3-\U00010cf9\U00010d28-\U00010d2f\U00010d3a-\U00010e5f\U00010e7f-\U00010eff\U00010f28-\U00010f2f\U00010f5a-\U00010fff\U0001104e-\U00011051\U00011070-\U0001107e\U000110c2-\U000110cc\U000110ce-\U000110cf\U000110e9-\U000110ef\U000110fa-\U000110ff\U00011135\U00011147-\U0001114f\U00011177-\U0001117f\U000111ce-\U000111cf\U000111e0\U000111f5-\U000111ff\U00011212\U0001123f-\U0001127f\U00011287\U00011289\U0001128e\U0001129e\U000112aa-\U000112af\U000112eb-\U000112ef\U000112fa-\U000112ff\U00011304\U0001130d-\U0001130e\U00011311-\U00011312\U00011329\U00011331\U00011334\U0001133a\U00011345-\U00011346\U00011349-\U0001134a\U0001134e-\U0001134f\U00011351-\U00011356\U00011358-\U0001135c\U00011364-\U00011365\U0001136d-\U0001136f\U00011375-\U000113ff\U0001145a\U0001145c\U0001145f-\U0001147f\U000114c8-\U000114cf\U000114da-\U0001157f\U000115b6-\U000115b7\U000115de-\U000115ff\U00011645-\U0001164f\U0001165a-\U0001165f\U0001166d-\U0001167f\U000116b8-\U000116bf\U000116ca-\U000116ff\U0001171b-\U0001171c\U0001172c-\U0001172f\U00011740-\U000117ff\U0001183c-\U0001189f\U000118f3-\U000118fe\U00011900-\U000119ff\U00011a48-\U00011a4f\U00011a84-\U00011a85\U00011aa3-\U00011abf\U00011af9-\U00011bff\U00011c09\U00011c37\U00011c46-\U00011c4f\U00011c6d-\U00011c6f\U00011c90-\U00011c91\U00011ca8\U00011cb7-\U00011cff\U00011d07\U00011d0a\U00011d37-\U00011d39\U00011d3b\U00011d3e\U00011d48-\U00011d4f\U00011d5a-\U00011d5f\U00011d66\U00011d69\U00011d8f\U00011d92\U00011d99-\U00011d9f\U00011daa-\U00011edf\U00011ef9-\U00011fff\U0001239a-\U000123ff\U0001246f\U00012475-\U0001247f\U00012544-\U00012fff\U0001342f-\U000143ff\U00014647-\U000167ff\U00016a39-\U00016a3f\U00016a5f\U00016a6a-\U00016a6d\U00016a70-\U00016acf\U00016aee-\U00016aef\U00016af6-\U00016aff\U00016b46-\U00016b4f\U00016b5a\U00016b62\U00016b78-\U00016b7c\U00016b90-\U00016e3f\U00016e9b-\U00016eff\U00016f45-\U00016f4f\U00016f7f-\U00016f8e\U00016fa0-\U00016fdf\U00016fe2-\U00016fff\U000187f2-\U000187ff\U00018af3-\U0001afff\U0001b11f-\U0001b16f\U0001b2fc-\U0001bbff\U0001bc6b-\U0001bc6f\U0001bc7d-\U0001bc7f\U0001bc89-\U0001bc8f\U0001bc9a-\U0001bc9b\U0001bca4-\U0001cfff\U0001d0f6-\U0001d0ff\U0001d127-\U0001d128\U0001d1e9-\U0001d1ff\U0001d246-\U0001d2df\U0001d2f4-\U0001d2ff\U0001d357-\U0001d35f\U0001d379-\U0001d3ff\U0001d455\U0001d49d\U0001d4a0-\U0001d4a1\U0001d4a3-\U0001d4a4\U0001d4a7-\U0001d4a8\U0001d4ad\U0001d4ba\U0001d4bc\U0001d4c4\U0001d506\U0001d50b-\U0001d50c\U0001d515\U0001d51d\U0001d53a\U0001d53f\U0001d545\U0001d547-\U0001d549\U0001d551\U0001d6a6-\U0001d6a7\U0001d7cc-\U0001d7cd\U0001da8c-\U0001da9a\U0001daa0\U0001dab0-\U0001dfff\U0001e007\U0001e019-\U0001e01a\U0001e022\U0001e025\U0001e02b-\U0001e7ff\U0001e8c5-\U0001e8c6\U0001e8d7-\U0001e8ff\U0001e94b-\U0001e94f\U0001e95a-\U0001e95d\U0001e960-\U0001ec70\U0001ecb5-\U0001edff\U0001ee04\U0001ee20\U0001ee23\U0001ee25-\U0001ee26\U0001ee28\U0001ee33\U0001ee38\U0001ee3a\U0001ee3c-\U0001ee41\U0001ee43-\U0001ee46\U0001ee48\U0001ee4a\U0001ee4c\U0001ee50\U0001ee53\U0001ee55-\U0001ee56\U0001ee58\U0001ee5a\U0001ee5c\U0001ee5e\U0001ee60\U0001ee63\U0001ee65-\U0001ee66\U0001ee6b\U0001ee73\U0001ee78\U0001ee7d\U0001ee7f\U0001ee8a\U0001ee9c-\U0001eea0\U0001eea4\U0001eeaa\U0001eebc-\U0001eeef\U0001eef2-\U0001efff\U0001f02c-\U0001f02f\U0001f094-\U0001f09f\U0001f0af-\U0001f0b0\U0001f0c0\U0001f0d0\U0001f0f6-\U0001f0ff\U0001f10d-\U0001f10f\U0001f16c-\U0001f16f\U0001f1ad-\U0001f1e5\U0001f203-\U0001f20f\U0001f23c-\U0001f23f\U0001f249-\U0001f24f\U0001f252-\U0001f25f\U0001f266-\U0001f2ff\U0001f6d5-\U0001f6df\U0001f6ed-\U0001f6ef\U0001f6fa-\U0001f6ff\U0001f774-\U0001f77f\U0001f7d9-\U0001f7ff\U0001f80c-\U0001f80f\U0001f848-\U0001f84f\U0001f85a-\U0001f85f\U0001f888-\U0001f88f\U0001f8ae-\U0001f8ff\U0001f90c-\U0001f90f\U0001f93f\U0001f971-\U0001f972\U0001f977-\U0001f979\U0001f97b\U0001f9a3-\U0001f9af\U0001f9ba-\U0001f9bf\U0001f9c3-\U0001f9cf\U0001fa00-\U0001fa5f\U0001fa6e-\U0001ffff\U0002a6d7-\U0002a6ff\U0002b735-\U0002b73f\U0002b81e-\U0002b81f\U0002cea2-\U0002ceaf\U0002ebe1-\U0002f7ff\U0002fa1e-\U000e0000\U000e0002-\U000e001f\U000e0080-\U000e00ff\U000e01f0-\U000effff\U000ffffe-\U000fffff\U0010fffe-\U0010ffff'
|
| 19 |
+
|
| 20 |
+
Co = '\ue000-\uf8ff\U000f0000-\U000ffffd\U00100000-\U0010fffd'
|
| 21 |
+
|
| 22 |
+
Cs = '\ud800-\udbff\\\udc00\udc01-\udfff'
|
| 23 |
+
|
| 24 |
+
Ll = 'a-z\xb5\xdf-\xf6\xf8-\xff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137-\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148-\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e-\u0180\u0183\u0185\u0188\u018c-\u018d\u0192\u0195\u0199-\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa-\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9-\u01ba\u01bd-\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc-\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef-\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0221\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233-\u0239\u023c\u023f-\u0240\u0242\u0247\u0249\u024b\u024d\u024f-\u0293\u0295-\u02af\u0371\u0373\u0377\u037b-\u037d\u0390\u03ac-\u03ce\u03d0-\u03d1\u03d5-\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef-\u03f3\u03f5\u03f8\u03fb-\u03fc\u0430-\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce-\u04cf\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f7\u04f9\u04fb\u04fd\u04ff\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0511\u0513\u0515\u0517\u0519\u051b\u051d\u051f\u0521\u0523\u0525\u0527\u0529\u052b\u052d\u052f\u0560-\u0588\u10d0-\u10fa\u10fd-\u10ff\u13f8-\u13fd\u1c80-\u1c88\u1d00-\u1d2b\u1d6b-\u1d77\u1d79-\u1d9a\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95-\u1e9d\u1e9f\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1efb\u1efd\u1eff-\u1f07\u1f10-\u1f15\u1f20-\u1f27\u1f30-\u1f37\u1f40-\u1f45\u1f50-\u1f57\u1f60-\u1f67\u1f70-\u1f7d\u1f80-\u1f87\u1f90-\u1f97\u1fa0-\u1fa7\u1fb0-\u1fb4\u1fb6-\u1fb7\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fc7\u1fd0-\u1fd3\u1fd6-\u1fd7\u1fe0-\u1fe7\u1ff2-\u1ff4\u1ff6-\u1ff7\u210a\u210e-\u210f\u2113\u212f\u2134\u2139\u213c-\u213d\u2146-\u2149\u214e\u2184\u2c30-\u2c5e\u2c61\u2c65-\u2c66\u2c68\u2c6a\u2c6c\u2c71\u2c73-\u2c74\u2c76-\u2c7b\u2c81\u2c83\u2c85\u2c87\u2c89\u2c8b\u2c8d\u2c8f\u2c91\u2c93\u2c95\u2c97\u2c99\u2c9b\u2c9d\u2c9f\u2ca1\u2ca3\u2ca5\u2ca7\u2ca9\u2cab\u2cad\u2caf\u2cb1\u2cb3\u2cb5\u2cb7\u2cb9\u2cbb\u2cbd\u2cbf\u2cc1\u2cc3\u2cc5\u2cc7\u2cc9\u2ccb\u2ccd\u2ccf\u2cd1\u2cd3\u2cd5\u2cd7\u2cd9\u2cdb\u2cdd\u2cdf\u2ce1\u2ce3-\u2ce4\u2cec\u2cee\u2cf3\u2d00-\u2d25\u2d27\u2d2d\ua641\ua643\ua645\ua647\ua649\ua64b\ua64d\ua64f\ua651\ua653\ua655\ua657\ua659\ua65b\ua65d\ua65f\ua661\ua663\ua665\ua667\ua669\ua66b\ua66d\ua681\ua683\ua685\ua687\ua689\ua68b\ua68d\ua68f\ua691\ua693\ua695\ua697\ua699\ua69b\ua723\ua725\ua727\ua729\ua72b\ua72d\ua72f-\ua731\ua733\ua735\ua737\ua739\ua73b\ua73d\ua73f\ua741\ua743\ua745\ua747\ua749\ua74b\ua74d\ua74f\ua751\ua753\ua755\ua757\ua759\ua75b\ua75d\ua75f\ua761\ua763\ua765\ua767\ua769\ua76b\ua76d\ua76f\ua771-\ua778\ua77a\ua77c\ua77f\ua781\ua783\ua785\ua787\ua78c\ua78e\ua791\ua793-\ua795\ua797\ua799\ua79b\ua79d\ua79f\ua7a1\ua7a3\ua7a5\ua7a7\ua7a9\ua7af\ua7b5\ua7b7\ua7b9\ua7fa\uab30-\uab5a\uab60-\uab65\uab70-\uabbf\ufb00-\ufb06\ufb13-\ufb17\uff41-\uff5a\U00010428-\U0001044f\U000104d8-\U000104fb\U00010cc0-\U00010cf2\U000118c0-\U000118df\U00016e60-\U00016e7f\U0001d41a-\U0001d433\U0001d44e-\U0001d454\U0001d456-\U0001d467\U0001d482-\U0001d49b\U0001d4b6-\U0001d4b9\U0001d4bb\U0001d4bd-\U0001d4c3\U0001d4c5-\U0001d4cf\U0001d4ea-\U0001d503\U0001d51e-\U0001d537\U0001d552-\U0001d56b\U0001d586-\U0001d59f\U0001d5ba-\U0001d5d3\U0001d5ee-\U0001d607\U0001d622-\U0001d63b\U0001d656-\U0001d66f\U0001d68a-\U0001d6a5\U0001d6c2-\U0001d6da\U0001d6dc-\U0001d6e1\U0001d6fc-\U0001d714\U0001d716-\U0001d71b\U0001d736-\U0001d74e\U0001d750-\U0001d755\U0001d770-\U0001d788\U0001d78a-\U0001d78f\U0001d7aa-\U0001d7c2\U0001d7c4-\U0001d7c9\U0001d7cb\U0001e922-\U0001e943'
|
| 25 |
+
|
| 26 |
+
Lm = '\u02b0-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0374\u037a\u0559\u0640\u06e5-\u06e6\u07f4-\u07f5\u07fa\u081a\u0824\u0828\u0971\u0e46\u0ec6\u10fc\u17d7\u1843\u1aa7\u1c78-\u1c7d\u1d2c-\u1d6a\u1d78\u1d9b-\u1dbf\u2071\u207f\u2090-\u209c\u2c7c-\u2c7d\u2d6f\u2e2f\u3005\u3031-\u3035\u303b\u309d-\u309e\u30fc-\u30fe\ua015\ua4f8-\ua4fd\ua60c\ua67f\ua69c-\ua69d\ua717-\ua71f\ua770\ua788\ua7f8-\ua7f9\ua9cf\ua9e6\uaa70\uaadd\uaaf3-\uaaf4\uab5c-\uab5f\uff70\uff9e-\uff9f\U00016b40-\U00016b43\U00016f93-\U00016f9f\U00016fe0-\U00016fe1'
|
| 27 |
+
|
| 28 |
+
Lo = '\xaa\xba\u01bb\u01c0-\u01c3\u0294\u05d0-\u05ea\u05ef-\u05f2\u0620-\u063f\u0641-\u064a\u066e-\u066f\u0671-\u06d3\u06d5\u06ee-\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u0800-\u0815\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u09fc\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0-\u0ae1\u0af9\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60-\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0-\u0ce1\u0cf1-\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32-\u0e33\u0e40-\u0e45\u0e81-\u0e82\u0e84\u0e87-\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa-\u0eab\u0ead-\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065-\u1066\u106e-\u1070\u1075-\u1081\u108e\u1100-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16f1-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17dc\u1820-\u1842\u1844-\u1878\u1880-\u1884\u1887-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae-\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c77\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5-\u1cf6\u2135-\u2138\u2d30-\u2d67\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3006\u303c\u3041-\u3096\u309f\u30a1-\u30fa\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua014\ua016-\ua48c\ua4d0-\ua4f7\ua500-\ua60b\ua610-\ua61f\ua62a-\ua62b\ua66e\ua6a0-\ua6e5\ua78f\ua7f7\ua7fb-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd-\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9e0-\ua9e4\ua9e7-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa6f\uaa71-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5-\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadc\uaae0-\uaaea\uaaf2\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff66-\uff6f\uff71-\uff9d\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\U00010000-\U0001000b\U0001000d-\U00010026\U00010028-\U0001003a\U0001003c-\U0001003d\U0001003f-\U0001004d\U00010050-\U0001005d\U00010080-\U000100fa\U00010280-\U0001029c\U000102a0-\U000102d0\U00010300-\U0001031f\U0001032d-\U00010340\U00010342-\U00010349\U00010350-\U00010375\U00010380-\U0001039d\U000103a0-\U000103c3\U000103c8-\U000103cf\U00010450-\U0001049d\U00010500-\U00010527\U00010530-\U00010563\U00010600-\U00010736\U00010740-\U00010755\U00010760-\U00010767\U00010800-\U00010805\U00010808\U0001080a-\U00010835\U00010837-\U00010838\U0001083c\U0001083f-\U00010855\U00010860-\U00010876\U00010880-\U0001089e\U000108e0-\U000108f2\U000108f4-\U000108f5\U00010900-\U00010915\U00010920-\U00010939\U00010980-\U000109b7\U000109be-\U000109bf\U00010a00\U00010a10-\U00010a13\U00010a15-\U00010a17\U00010a19-\U00010a35\U00010a60-\U00010a7c\U00010a80-\U00010a9c\U00010ac0-\U00010ac7\U00010ac9-\U00010ae4\U00010b00-\U00010b35\U00010b40-\U00010b55\U00010b60-\U00010b72\U00010b80-\U00010b91\U00010c00-\U00010c48\U00010d00-\U00010d23\U00010f00-\U00010f1c\U00010f27\U00010f30-\U00010f45\U00011003-\U00011037\U00011083-\U000110af\U000110d0-\U000110e8\U00011103-\U00011126\U00011144\U00011150-\U00011172\U00011176\U00011183-\U000111b2\U000111c1-\U000111c4\U000111da\U000111dc\U00011200-\U00011211\U00011213-\U0001122b\U00011280-\U00011286\U00011288\U0001128a-\U0001128d\U0001128f-\U0001129d\U0001129f-\U000112a8\U000112b0-\U000112de\U00011305-\U0001130c\U0001130f-\U00011310\U00011313-\U00011328\U0001132a-\U00011330\U00011332-\U00011333\U00011335-\U00011339\U0001133d\U00011350\U0001135d-\U00011361\U00011400-\U00011434\U00011447-\U0001144a\U00011480-\U000114af\U000114c4-\U000114c5\U000114c7\U00011580-\U000115ae\U000115d8-\U000115db\U00011600-\U0001162f\U00011644\U00011680-\U000116aa\U00011700-\U0001171a\U00011800-\U0001182b\U000118ff\U00011a00\U00011a0b-\U00011a32\U00011a3a\U00011a50\U00011a5c-\U00011a83\U00011a86-\U00011a89\U00011a9d\U00011ac0-\U00011af8\U00011c00-\U00011c08\U00011c0a-\U00011c2e\U00011c40\U00011c72-\U00011c8f\U00011d00-\U00011d06\U00011d08-\U00011d09\U00011d0b-\U00011d30\U00011d46\U00011d60-\U00011d65\U00011d67-\U00011d68\U00011d6a-\U00011d89\U00011d98\U00011ee0-\U00011ef2\U00012000-\U00012399\U00012480-\U00012543\U00013000-\U0001342e\U00014400-\U00014646\U00016800-\U00016a38\U00016a40-\U00016a5e\U00016ad0-\U00016aed\U00016b00-\U00016b2f\U00016b63-\U00016b77\U00016b7d-\U00016b8f\U00016f00-\U00016f44\U00016f50\U00017000-\U000187f1\U00018800-\U00018af2\U0001b000-\U0001b11e\U0001b170-\U0001b2fb\U0001bc00-\U0001bc6a\U0001bc70-\U0001bc7c\U0001bc80-\U0001bc88\U0001bc90-\U0001bc99\U0001e800-\U0001e8c4\U0001ee00-\U0001ee03\U0001ee05-\U0001ee1f\U0001ee21-\U0001ee22\U0001ee24\U0001ee27\U0001ee29-\U0001ee32\U0001ee34-\U0001ee37\U0001ee39\U0001ee3b\U0001ee42\U0001ee47\U0001ee49\U0001ee4b\U0001ee4d-\U0001ee4f\U0001ee51-\U0001ee52\U0001ee54\U0001ee57\U0001ee59\U0001ee5b\U0001ee5d\U0001ee5f\U0001ee61-\U0001ee62\U0001ee64\U0001ee67-\U0001ee6a\U0001ee6c-\U0001ee72\U0001ee74-\U0001ee77\U0001ee79-\U0001ee7c\U0001ee7e\U0001ee80-\U0001ee89\U0001ee8b-\U0001ee9b\U0001eea1-\U0001eea3\U0001eea5-\U0001eea9\U0001eeab-\U0001eebb\U00020000-\U0002a6d6\U0002a700-\U0002b734\U0002b740-\U0002b81d\U0002b820-\U0002cea1\U0002ceb0-\U0002ebe0\U0002f800-\U0002fa1d'
|
| 29 |
+
|
| 30 |
+
Lt = '\u01c5\u01c8\u01cb\u01f2\u1f88-\u1f8f\u1f98-\u1f9f\u1fa8-\u1faf\u1fbc\u1fcc\u1ffc'
|
| 31 |
+
|
| 32 |
+
Lu = 'A-Z\xc0-\xd6\xd8-\xde\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178-\u0179\u017b\u017d\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018b\u018e-\u0191\u0193-\u0194\u0196-\u0198\u019c-\u019d\u019f-\u01a0\u01a2\u01a4\u01a6-\u01a7\u01a9\u01ac\u01ae-\u01af\u01b1-\u01b3\u01b5\u01b7-\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6-\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u023a-\u023b\u023d-\u023e\u0241\u0243-\u0246\u0248\u024a\u024c\u024e\u0370\u0372\u0376\u037f\u0386\u0388-\u038a\u038c\u038e-\u038f\u0391-\u03a1\u03a3-\u03ab\u03cf\u03d2-\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u03f7\u03f9-\u03fa\u03fd-\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0-\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f6\u04f8\u04fa\u04fc\u04fe\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0510\u0512\u0514\u0516\u0518\u051a\u051c\u051e\u0520\u0522\u0524\u0526\u0528\u052a\u052c\u052e\u0531-\u0556\u10a0-\u10c5\u10c7\u10cd\u13a0-\u13f5\u1c90-\u1cba\u1cbd-\u1cbf\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1e9e\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1efa\u1efc\u1efe\u1f08-\u1f0f\u1f18-\u1f1d\u1f28-\u1f2f\u1f38-\u1f3f\u1f48-\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68-\u1f6f\u1fb8-\u1fbb\u1fc8-\u1fcb\u1fd8-\u1fdb\u1fe8-\u1fec\u1ff8-\u1ffb\u2102\u2107\u210b-\u210d\u2110-\u2112\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u2130-\u2133\u213e-\u213f\u2145\u2183\u2c00-\u2c2e\u2c60\u2c62-\u2c64\u2c67\u2c69\u2c6b\u2c6d-\u2c70\u2c72\u2c75\u2c7e-\u2c80\u2c82\u2c84\u2c86\u2c88\u2c8a\u2c8c\u2c8e\u2c90\u2c92\u2c94\u2c96\u2c98\u2c9a\u2c9c\u2c9e\u2ca0\u2ca2\u2ca4\u2ca6\u2ca8\u2caa\u2cac\u2cae\u2cb0\u2cb2\u2cb4\u2cb6\u2cb8\u2cba\u2cbc\u2cbe\u2cc0\u2cc2\u2cc4\u2cc6\u2cc8\u2cca\u2ccc\u2cce\u2cd0\u2cd2\u2cd4\u2cd6\u2cd8\u2cda\u2cdc\u2cde\u2ce0\u2ce2\u2ceb\u2ced\u2cf2\ua640\ua642\ua644\ua646\ua648\ua64a\ua64c\ua64e\ua650\ua652\ua654\ua656\ua658\ua65a\ua65c\ua65e\ua660\ua662\ua664\ua666\ua668\ua66a\ua66c\ua680\ua682\ua684\ua686\ua688\ua68a\ua68c\ua68e\ua690\ua692\ua694\ua696\ua698\ua69a\ua722\ua724\ua726\ua728\ua72a\ua72c\ua72e\ua732\ua734\ua736\ua738\ua73a\ua73c\ua73e\ua740\ua742\ua744\ua746\ua748\ua74a\ua74c\ua74e\ua750\ua752\ua754\ua756\ua758\ua75a\ua75c\ua75e\ua760\ua762\ua764\ua766\ua768\ua76a\ua76c\ua76e\ua779\ua77b\ua77d-\ua77e\ua780\ua782\ua784\ua786\ua78b\ua78d\ua790\ua792\ua796\ua798\ua79a\ua79c\ua79e\ua7a0\ua7a2\ua7a4\ua7a6\ua7a8\ua7aa-\ua7ae\ua7b0-\ua7b4\ua7b6\ua7b8\uff21-\uff3a\U00010400-\U00010427\U000104b0-\U000104d3\U00010c80-\U00010cb2\U000118a0-\U000118bf\U00016e40-\U00016e5f\U0001d400-\U0001d419\U0001d434-\U0001d44d\U0001d468-\U0001d481\U0001d49c\U0001d49e-\U0001d49f\U0001d4a2\U0001d4a5-\U0001d4a6\U0001d4a9-\U0001d4ac\U0001d4ae-\U0001d4b5\U0001d4d0-\U0001d4e9\U0001d504-\U0001d505\U0001d507-\U0001d50a\U0001d50d-\U0001d514\U0001d516-\U0001d51c\U0001d538-\U0001d539\U0001d53b-\U0001d53e\U0001d540-\U0001d544\U0001d546\U0001d54a-\U0001d550\U0001d56c-\U0001d585\U0001d5a0-\U0001d5b9\U0001d5d4-\U0001d5ed\U0001d608-\U0001d621\U0001d63c-\U0001d655\U0001d670-\U0001d689\U0001d6a8-\U0001d6c0\U0001d6e2-\U0001d6fa\U0001d71c-\U0001d734\U0001d756-\U0001d76e\U0001d790-\U0001d7a8\U0001d7ca\U0001e900-\U0001e921'
|
| 33 |
+
|
| 34 |
+
Mc = '\u0903\u093b\u093e-\u0940\u0949-\u094c\u094e-\u094f\u0982-\u0983\u09be-\u09c0\u09c7-\u09c8\u09cb-\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb-\u0acc\u0b02-\u0b03\u0b3e\u0b40\u0b47-\u0b48\u0b4b-\u0b4c\u0b57\u0bbe-\u0bbf\u0bc1-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82-\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7-\u0cc8\u0cca-\u0ccb\u0cd5-\u0cd6\u0d02-\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82-\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2-\u0df3\u0f3e-\u0f3f\u0f7f\u102b-\u102c\u1031\u1038\u103b-\u103c\u1056-\u1057\u1062-\u1064\u1067-\u106d\u1083-\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7-\u17c8\u1923-\u1926\u1929-\u192b\u1930-\u1931\u1933-\u1938\u1a19-\u1a1a\u1a55\u1a57\u1a61\u1a63-\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b44\u1b82\u1ba1\u1ba6-\u1ba7\u1baa\u1be7\u1bea-\u1bec\u1bee\u1bf2-\u1bf3\u1c24-\u1c2b\u1c34-\u1c35\u1ce1\u1cf2-\u1cf3\u1cf7\u302e-\u302f\ua823-\ua824\ua827\ua880-\ua881\ua8b4-\ua8c3\ua952-\ua953\ua983\ua9b4-\ua9b5\ua9ba-\ua9bb\ua9bd-\ua9c0\uaa2f-\uaa30\uaa33-\uaa34\uaa4d\uaa7b\uaa7d\uaaeb\uaaee-\uaaef\uaaf5\uabe3-\uabe4\uabe6-\uabe7\uabe9-\uabea\uabec\U00011000\U00011002\U00011082\U000110b0-\U000110b2\U000110b7-\U000110b8\U0001112c\U00011145-\U00011146\U00011182\U000111b3-\U000111b5\U000111bf-\U000111c0\U0001122c-\U0001122e\U00011232-\U00011233\U00011235\U000112e0-\U000112e2\U00011302-\U00011303\U0001133e-\U0001133f\U00011341-\U00011344\U00011347-\U00011348\U0001134b-\U0001134d\U00011357\U00011362-\U00011363\U00011435-\U00011437\U00011440-\U00011441\U00011445\U000114b0-\U000114b2\U000114b9\U000114bb-\U000114be\U000114c1\U000115af-\U000115b1\U000115b8-\U000115bb\U000115be\U00011630-\U00011632\U0001163b-\U0001163c\U0001163e\U000116ac\U000116ae-\U000116af\U000116b6\U00011720-\U00011721\U00011726\U0001182c-\U0001182e\U00011838\U00011a39\U00011a57-\U00011a58\U00011a97\U00011c2f\U00011c3e\U00011ca9\U00011cb1\U00011cb4\U00011d8a-\U00011d8e\U00011d93-\U00011d94\U00011d96\U00011ef5-\U00011ef6\U00016f51-\U00016f7e\U0001d165-\U0001d166\U0001d16d-\U0001d172'
|
| 35 |
+
|
| 36 |
+
Me = '\u0488-\u0489\u1abe\u20dd-\u20e0\u20e2-\u20e4\ua670-\ua672'
|
| 37 |
+
|
| 38 |
+
Mn = '\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0902\u093a\u093c\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2-\u09e3\u09fe\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0afa-\u0aff\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62-\u0b63\u0b82\u0bc0\u0bcd\u0c00\u0c04\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc6\u0ccc-\u0ccd\u0ce2-\u0ce3\u0d00-\u0d01\u0d3b-\u0d3c\u0d41-\u0d44\u0d4d\u0d62-\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u1885-\u1886\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302d\u3099-\u309a\ua66f\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1\ua802\ua806\ua80b\ua825-\ua826\ua8c4-\ua8c5\ua8e0-\ua8f1\ua8ff\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\U000101fd\U000102e0\U00010376-\U0001037a\U00010a01-\U00010a03\U00010a05-\U00010a06\U00010a0c-\U00010a0f\U00010a38-\U00010a3a\U00010a3f\U00010ae5-\U00010ae6\U00010d24-\U00010d27\U00010f46-\U00010f50\U00011001\U00011038-\U00011046\U0001107f-\U00011081\U000110b3-\U000110b6\U000110b9-\U000110ba\U00011100-\U00011102\U00011127-\U0001112b\U0001112d-\U00011134\U00011173\U00011180-\U00011181\U000111b6-\U000111be\U000111c9-\U000111cc\U0001122f-\U00011231\U00011234\U00011236-\U00011237\U0001123e\U000112df\U000112e3-\U000112ea\U00011300-\U00011301\U0001133b-\U0001133c\U00011340\U00011366-\U0001136c\U00011370-\U00011374\U00011438-\U0001143f\U00011442-\U00011444\U00011446\U0001145e\U000114b3-\U000114b8\U000114ba\U000114bf-\U000114c0\U000114c2-\U000114c3\U000115b2-\U000115b5\U000115bc-\U000115bd\U000115bf-\U000115c0\U000115dc-\U000115dd\U00011633-\U0001163a\U0001163d\U0001163f-\U00011640\U000116ab\U000116ad\U000116b0-\U000116b5\U000116b7\U0001171d-\U0001171f\U00011722-\U00011725\U00011727-\U0001172b\U0001182f-\U00011837\U00011839-\U0001183a\U00011a01-\U00011a0a\U00011a33-\U00011a38\U00011a3b-\U00011a3e\U00011a47\U00011a51-\U00011a56\U00011a59-\U00011a5b\U00011a8a-\U00011a96\U00011a98-\U00011a99\U00011c30-\U00011c36\U00011c38-\U00011c3d\U00011c3f\U00011c92-\U00011ca7\U00011caa-\U00011cb0\U00011cb2-\U00011cb3\U00011cb5-\U00011cb6\U00011d31-\U00011d36\U00011d3a\U00011d3c-\U00011d3d\U00011d3f-\U00011d45\U00011d47\U00011d90-\U00011d91\U00011d95\U00011d97\U00011ef3-\U00011ef4\U00016af0-\U00016af4\U00016b30-\U00016b36\U00016f8f-\U00016f92\U0001bc9d-\U0001bc9e\U0001d167-\U0001d169\U0001d17b-\U0001d182\U0001d185-\U0001d18b\U0001d1aa-\U0001d1ad\U0001d242-\U0001d244\U0001da00-\U0001da36\U0001da3b-\U0001da6c\U0001da75\U0001da84\U0001da9b-\U0001da9f\U0001daa1-\U0001daaf\U0001e000-\U0001e006\U0001e008-\U0001e018\U0001e01b-\U0001e021\U0001e023-\U0001e024\U0001e026-\U0001e02a\U0001e8d0-\U0001e8d6\U0001e944-\U0001e94a\U000e0100-\U000e01ef'
|
| 39 |
+
|
| 40 |
+
Nd = '0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0de6-\u0def\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\ua9f0-\ua9f9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19\U000104a0-\U000104a9\U00010d30-\U00010d39\U00011066-\U0001106f\U000110f0-\U000110f9\U00011136-\U0001113f\U000111d0-\U000111d9\U000112f0-\U000112f9\U00011450-\U00011459\U000114d0-\U000114d9\U00011650-\U00011659\U000116c0-\U000116c9\U00011730-\U00011739\U000118e0-\U000118e9\U00011c50-\U00011c59\U00011d50-\U00011d59\U00011da0-\U00011da9\U00016a60-\U00016a69\U00016b50-\U00016b59\U0001d7ce-\U0001d7ff\U0001e950-\U0001e959'
|
| 41 |
+
|
| 42 |
+
Nl = '\u16ee-\u16f0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303a\ua6e6-\ua6ef\U00010140-\U00010174\U00010341\U0001034a\U000103d1-\U000103d5\U00012400-\U0001246e'
|
| 43 |
+
|
| 44 |
+
No = '\xb2-\xb3\xb9\xbc-\xbe\u09f4-\u09f9\u0b72-\u0b77\u0bf0-\u0bf2\u0c78-\u0c7e\u0d58-\u0d5e\u0d70-\u0d78\u0f2a-\u0f33\u1369-\u137c\u17f0-\u17f9\u19da\u2070\u2074-\u2079\u2080-\u2089\u2150-\u215f\u2189\u2460-\u249b\u24ea-\u24ff\u2776-\u2793\u2cfd\u3192-\u3195\u3220-\u3229\u3248-\u324f\u3251-\u325f\u3280-\u3289\u32b1-\u32bf\ua830-\ua835\U00010107-\U00010133\U00010175-\U00010178\U0001018a-\U0001018b\U000102e1-\U000102fb\U00010320-\U00010323\U00010858-\U0001085f\U00010879-\U0001087f\U000108a7-\U000108af\U000108fb-\U000108ff\U00010916-\U0001091b\U000109bc-\U000109bd\U000109c0-\U000109cf\U000109d2-\U000109ff\U00010a40-\U00010a48\U00010a7d-\U00010a7e\U00010a9d-\U00010a9f\U00010aeb-\U00010aef\U00010b58-\U00010b5f\U00010b78-\U00010b7f\U00010ba9-\U00010baf\U00010cfa-\U00010cff\U00010e60-\U00010e7e\U00010f1d-\U00010f26\U00010f51-\U00010f54\U00011052-\U00011065\U000111e1-\U000111f4\U0001173a-\U0001173b\U000118ea-\U000118f2\U00011c5a-\U00011c6c\U00016b5b-\U00016b61\U00016e80-\U00016e96\U0001d2e0-\U0001d2f3\U0001d360-\U0001d378\U0001e8c7-\U0001e8cf\U0001ec71-\U0001ecab\U0001ecad-\U0001ecaf\U0001ecb1-\U0001ecb4\U0001f100-\U0001f10c'
|
| 45 |
+
|
| 46 |
+
Pc = '_\u203f-\u2040\u2054\ufe33-\ufe34\ufe4d-\ufe4f\uff3f'
|
| 47 |
+
|
| 48 |
+
Pd = '\\-\u058a\u05be\u1400\u1806\u2010-\u2015\u2e17\u2e1a\u2e3a-\u2e3b\u2e40\u301c\u3030\u30a0\ufe31-\ufe32\ufe58\ufe63\uff0d'
|
| 49 |
+
|
| 50 |
+
Pe = ')\\]}\u0f3b\u0f3d\u169c\u2046\u207e\u208e\u2309\u230b\u232a\u2769\u276b\u276d\u276f\u2771\u2773\u2775\u27c6\u27e7\u27e9\u27eb\u27ed\u27ef\u2984\u2986\u2988\u298a\u298c\u298e\u2990\u2992\u2994\u2996\u2998\u29d9\u29db\u29fd\u2e23\u2e25\u2e27\u2e29\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e-\u301f\ufd3e\ufe18\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42\ufe44\ufe48\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff60\uff63'
|
| 51 |
+
|
| 52 |
+
Pf = '\xbb\u2019\u201d\u203a\u2e03\u2e05\u2e0a\u2e0d\u2e1d\u2e21'
|
| 53 |
+
|
| 54 |
+
Pi = '\xab\u2018\u201b-\u201c\u201f\u2039\u2e02\u2e04\u2e09\u2e0c\u2e1c\u2e20'
|
| 55 |
+
|
| 56 |
+
Po = "!-#%-'*,.-/:-;?-@\\\\\xa1\xa7\xb6-\xb7\xbf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3-\u05f4\u0609-\u060a\u060c-\u060d\u061b\u061e-\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964-\u0965\u0970\u09fd\u0a76\u0af0\u0c84\u0df4\u0e4f\u0e5a-\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9-\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d-\u166e\u16eb-\u16ed\u1735-\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944-\u1945\u1a1e-\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e-\u1c7f\u1cc0-\u1cc7\u1cd3\u2016-\u2017\u2020-\u2027\u2030-\u2038\u203b-\u203e\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205e\u2cf9-\u2cfc\u2cfe-\u2cff\u2d70\u2e00-\u2e01\u2e06-\u2e08\u2e0b\u2e0e-\u2e16\u2e18-\u2e19\u2e1b\u2e1e-\u2e1f\u2e2a-\u2e2e\u2e30-\u2e39\u2e3c-\u2e3f\u2e41\u2e43-\u2e4e\u3001-\u3003\u303d\u30fb\ua4fe-\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce-\ua8cf\ua8f8-\ua8fa\ua8fc\ua92e-\ua92f\ua95f\ua9c1-\ua9cd\ua9de-\ua9df\uaa5c-\uaa5f\uaade-\uaadf\uaaf0-\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45-\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a-\ufe6b\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e-\uff0f\uff1a-\uff1b\uff1f-\uff20\uff3c\uff61\uff64-\uff65\U00010100-\U00010102\U0001039f\U000103d0\U0001056f\U00010857\U0001091f\U0001093f\U00010a50-\U00010a58\U00010a7f\U00010af0-\U00010af6\U00010b39-\U00010b3f\U00010b99-\U00010b9c\U00010f55-\U00010f59\U00011047-\U0001104d\U000110bb-\U000110bc\U000110be-\U000110c1\U00011140-\U00011143\U00011174-\U00011175\U000111c5-\U000111c8\U000111cd\U000111db\U000111dd-\U000111df\U00011238-\U0001123d\U000112a9\U0001144b-\U0001144f\U0001145b\U0001145d\U000114c6\U000115c1-\U000115d7\U00011641-\U00011643\U00011660-\U0001166c\U0001173c-\U0001173e\U0001183b\U00011a3f-\U00011a46\U00011a9a-\U00011a9c\U00011a9e-\U00011aa2\U00011c41-\U00011c45\U00011c70-\U00011c71\U00011ef7-\U00011ef8\U00012470-\U00012474\U00016a6e-\U00016a6f\U00016af5\U00016b37-\U00016b3b\U00016b44\U00016e97-\U00016e9a\U0001bc9f\U0001da87-\U0001da8b\U0001e95e-\U0001e95f"
|
| 57 |
+
|
| 58 |
+
Ps = '(\\[{\u0f3a\u0f3c\u169b\u201a\u201e\u2045\u207d\u208d\u2308\u230a\u2329\u2768\u276a\u276c\u276e\u2770\u2772\u2774\u27c5\u27e6\u27e8\u27ea\u27ec\u27ee\u2983\u2985\u2987\u2989\u298b\u298d\u298f\u2991\u2993\u2995\u2997\u29d8\u29da\u29fc\u2e22\u2e24\u2e26\u2e28\u2e42\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d\ufd3f\ufe17\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41\ufe43\ufe47\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff5f\uff62'
|
| 59 |
+
|
| 60 |
+
Sc = '$\xa2-\xa5\u058f\u060b\u07fe-\u07ff\u09f2-\u09f3\u09fb\u0af1\u0bf9\u0e3f\u17db\u20a0-\u20bf\ua838\ufdfc\ufe69\uff04\uffe0-\uffe1\uffe5-\uffe6\U0001ecb0'
|
| 61 |
+
|
| 62 |
+
Sk = '\\^`\xa8\xaf\xb4\xb8\u02c2-\u02c5\u02d2-\u02df\u02e5-\u02eb\u02ed\u02ef-\u02ff\u0375\u0384-\u0385\u1fbd\u1fbf-\u1fc1\u1fcd-\u1fcf\u1fdd-\u1fdf\u1fed-\u1fef\u1ffd-\u1ffe\u309b-\u309c\ua700-\ua716\ua720-\ua721\ua789-\ua78a\uab5b\ufbb2-\ufbc1\uff3e\uff40\uffe3\U0001f3fb-\U0001f3ff'
|
| 63 |
+
|
| 64 |
+
Sm = '+<->|~\xac\xb1\xd7\xf7\u03f6\u0606-\u0608\u2044\u2052\u207a-\u207c\u208a-\u208c\u2118\u2140-\u2144\u214b\u2190-\u2194\u219a-\u219b\u21a0\u21a3\u21a6\u21ae\u21ce-\u21cf\u21d2\u21d4\u21f4-\u22ff\u2320-\u2321\u237c\u239b-\u23b3\u23dc-\u23e1\u25b7\u25c1\u25f8-\u25ff\u266f\u27c0-\u27c4\u27c7-\u27e5\u27f0-\u27ff\u2900-\u2982\u2999-\u29d7\u29dc-\u29fb\u29fe-\u2aff\u2b30-\u2b44\u2b47-\u2b4c\ufb29\ufe62\ufe64-\ufe66\uff0b\uff1c-\uff1e\uff5c\uff5e\uffe2\uffe9-\uffec\U0001d6c1\U0001d6db\U0001d6fb\U0001d715\U0001d735\U0001d74f\U0001d76f\U0001d789\U0001d7a9\U0001d7c3\U0001eef0-\U0001eef1'
|
| 65 |
+
|
| 66 |
+
So = '\xa6\xa9\xae\xb0\u0482\u058d-\u058e\u060e-\u060f\u06de\u06e9\u06fd-\u06fe\u07f6\u09fa\u0b70\u0bf3-\u0bf8\u0bfa\u0c7f\u0d4f\u0d79\u0f01-\u0f03\u0f13\u0f15-\u0f17\u0f1a-\u0f1f\u0f34\u0f36\u0f38\u0fbe-\u0fc5\u0fc7-\u0fcc\u0fce-\u0fcf\u0fd5-\u0fd8\u109e-\u109f\u1390-\u1399\u1940\u19de-\u19ff\u1b61-\u1b6a\u1b74-\u1b7c\u2100-\u2101\u2103-\u2106\u2108-\u2109\u2114\u2116-\u2117\u211e-\u2123\u2125\u2127\u2129\u212e\u213a-\u213b\u214a\u214c-\u214d\u214f\u218a-\u218b\u2195-\u2199\u219c-\u219f\u21a1-\u21a2\u21a4-\u21a5\u21a7-\u21ad\u21af-\u21cd\u21d0-\u21d1\u21d3\u21d5-\u21f3\u2300-\u2307\u230c-\u231f\u2322-\u2328\u232b-\u237b\u237d-\u239a\u23b4-\u23db\u23e2-\u2426\u2440-\u244a\u249c-\u24e9\u2500-\u25b6\u25b8-\u25c0\u25c2-\u25f7\u2600-\u266e\u2670-\u2767\u2794-\u27bf\u2800-\u28ff\u2b00-\u2b2f\u2b45-\u2b46\u2b4d-\u2b73\u2b76-\u2b95\u2b98-\u2bc8\u2bca-\u2bfe\u2ce5-\u2cea\u2e80-\u2e99\u2e9b-\u2ef3\u2f00-\u2fd5\u2ff0-\u2ffb\u3004\u3012-\u3013\u3020\u3036-\u3037\u303e-\u303f\u3190-\u3191\u3196-\u319f\u31c0-\u31e3\u3200-\u321e\u322a-\u3247\u3250\u3260-\u327f\u328a-\u32b0\u32c0-\u32fe\u3300-\u33ff\u4dc0-\u4dff\ua490-\ua4c6\ua828-\ua82b\ua836-\ua837\ua839\uaa77-\uaa79\ufdfd\uffe4\uffe8\uffed-\uffee\ufffc-\ufffd\U00010137-\U0001013f\U00010179-\U00010189\U0001018c-\U0001018e\U00010190-\U0001019b\U000101a0\U000101d0-\U000101fc\U00010877-\U00010878\U00010ac8\U0001173f\U00016b3c-\U00016b3f\U00016b45\U0001bc9c\U0001d000-\U0001d0f5\U0001d100-\U0001d126\U0001d129-\U0001d164\U0001d16a-\U0001d16c\U0001d183-\U0001d184\U0001d18c-\U0001d1a9\U0001d1ae-\U0001d1e8\U0001d200-\U0001d241\U0001d245\U0001d300-\U0001d356\U0001d800-\U0001d9ff\U0001da37-\U0001da3a\U0001da6d-\U0001da74\U0001da76-\U0001da83\U0001da85-\U0001da86\U0001ecac\U0001f000-\U0001f02b\U0001f030-\U0001f093\U0001f0a0-\U0001f0ae\U0001f0b1-\U0001f0bf\U0001f0c1-\U0001f0cf\U0001f0d1-\U0001f0f5\U0001f110-\U0001f16b\U0001f170-\U0001f1ac\U0001f1e6-\U0001f202\U0001f210-\U0001f23b\U0001f240-\U0001f248\U0001f250-\U0001f251\U0001f260-\U0001f265\U0001f300-\U0001f3fa\U0001f400-\U0001f6d4\U0001f6e0-\U0001f6ec\U0001f6f0-\U0001f6f9\U0001f700-\U0001f773\U0001f780-\U0001f7d8\U0001f800-\U0001f80b\U0001f810-\U0001f847\U0001f850-\U0001f859\U0001f860-\U0001f887\U0001f890-\U0001f8ad\U0001f900-\U0001f90b\U0001f910-\U0001f93e\U0001f940-\U0001f970\U0001f973-\U0001f976\U0001f97a\U0001f97c-\U0001f9a2\U0001f9b0-\U0001f9b9\U0001f9c0-\U0001f9c2\U0001f9d0-\U0001f9ff\U0001fa60-\U0001fa6d'
|
| 67 |
+
|
| 68 |
+
Zl = '\u2028'
|
| 69 |
+
|
| 70 |
+
Zp = '\u2029'
|
| 71 |
+
|
| 72 |
+
Zs = ' \xa0\u1680\u2000-\u200a\u202f\u205f\u3000'
|
| 73 |
+
|
| 74 |
+
xid_continue = '0-9A-Z_a-z\xaa\xb5\xb7\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376-\u0377\u037b-\u037d\u037f\u0386-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u05d0-\u05ea\u05ef-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u07fd\u0800-\u082d\u0840-\u085b\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u08d3-\u08e1\u08e3-\u0963\u0966-\u096f\u0971-\u0983\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7-\u09c8\u09cb-\u09ce\u09d7\u09dc-\u09dd\u09df-\u09e3\u09e6-\u09f1\u09fc\u09fe\u0a01-\u0a03\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a3c\u0a3e-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0af9-\u0aff\u0b01-\u0b03\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47-\u0b48\u0b4b-\u0b4d\u0b56-\u0b57\u0b5c-\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82-\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c00-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c58-\u0c5a\u0c60-\u0c63\u0c66-\u0c6f\u0c80-\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5-\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1-\u0cf2\u0d00-\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d54-\u0d57\u0d5f-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82-\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2-\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81-\u0e82\u0e84\u0e87-\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa-\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18-\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1369-\u1371\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772-\u1773\u1780-\u17d3\u17d7\u17dc-\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1878\u1880-\u18aa\u18b0-\u18f5\u1900-\u191e\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19da\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1ab0-\u1abd\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1cd0-\u1cd2\u1cd4-\u1cf9\u1d00-\u1df9\u1dfb-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u203f-\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099-\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua7b9\ua7f7-\ua827\ua840-\ua873\ua880-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua8fd-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\ua9e0-\ua9fe\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabea\uabec-\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufc5d\ufc64-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdf9\ufe00-\ufe0f\ufe20-\ufe2f\ufe33-\ufe34\ufe4d-\ufe4f\ufe71\ufe73\ufe77\ufe79\ufe7b\ufe7d\ufe7f-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\U00010000-\U0001000b\U0001000d-\U00010026\U00010028-\U0001003a\U0001003c-\U0001003d\U0001003f-\U0001004d\U00010050-\U0001005d\U00010080-\U000100fa\U00010140-\U00010174\U000101fd\U00010280-\U0001029c\U000102a0-\U000102d0\U000102e0\U00010300-\U0001031f\U0001032d-\U0001034a\U00010350-\U0001037a\U00010380-\U0001039d\U000103a0-\U000103c3\U000103c8-\U000103cf\U000103d1-\U000103d5\U00010400-\U0001049d\U000104a0-\U000104a9\U000104b0-\U000104d3\U000104d8-\U000104fb\U00010500-\U00010527\U00010530-\U00010563\U00010600-\U00010736\U00010740-\U00010755\U00010760-\U00010767\U00010800-\U00010805\U00010808\U0001080a-\U00010835\U00010837-\U00010838\U0001083c\U0001083f-\U00010855\U00010860-\U00010876\U00010880-\U0001089e\U000108e0-\U000108f2\U000108f4-\U000108f5\U00010900-\U00010915\U00010920-\U00010939\U00010980-\U000109b7\U000109be-\U000109bf\U00010a00-\U00010a03\U00010a05-\U00010a06\U00010a0c-\U00010a13\U00010a15-\U00010a17\U00010a19-\U00010a35\U00010a38-\U00010a3a\U00010a3f\U00010a60-\U00010a7c\U00010a80-\U00010a9c\U00010ac0-\U00010ac7\U00010ac9-\U00010ae6\U00010b00-\U00010b35\U00010b40-\U00010b55\U00010b60-\U00010b72\U00010b80-\U00010b91\U00010c00-\U00010c48\U00010c80-\U00010cb2\U00010cc0-\U00010cf2\U00010d00-\U00010d27\U00010d30-\U00010d39\U00010f00-\U00010f1c\U00010f27\U00010f30-\U00010f50\U00011000-\U00011046\U00011066-\U0001106f\U0001107f-\U000110ba\U000110d0-\U000110e8\U000110f0-\U000110f9\U00011100-\U00011134\U00011136-\U0001113f\U00011144-\U00011146\U00011150-\U00011173\U00011176\U00011180-\U000111c4\U000111c9-\U000111cc\U000111d0-\U000111da\U000111dc\U00011200-\U00011211\U00011213-\U00011237\U0001123e\U00011280-\U00011286\U00011288\U0001128a-\U0001128d\U0001128f-\U0001129d\U0001129f-\U000112a8\U000112b0-\U000112ea\U000112f0-\U000112f9\U00011300-\U00011303\U00011305-\U0001130c\U0001130f-\U00011310\U00011313-\U00011328\U0001132a-\U00011330\U00011332-\U00011333\U00011335-\U00011339\U0001133b-\U00011344\U00011347-\U00011348\U0001134b-\U0001134d\U00011350\U00011357\U0001135d-\U00011363\U00011366-\U0001136c\U00011370-\U00011374\U00011400-\U0001144a\U00011450-\U00011459\U0001145e\U00011480-\U000114c5\U000114c7\U000114d0-\U000114d9\U00011580-\U000115b5\U000115b8-\U000115c0\U000115d8-\U000115dd\U00011600-\U00011640\U00011644\U00011650-\U00011659\U00011680-\U000116b7\U000116c0-\U000116c9\U00011700-\U0001171a\U0001171d-\U0001172b\U00011730-\U00011739\U00011800-\U0001183a\U000118a0-\U000118e9\U000118ff\U00011a00-\U00011a3e\U00011a47\U00011a50-\U00011a83\U00011a86-\U00011a99\U00011a9d\U00011ac0-\U00011af8\U00011c00-\U00011c08\U00011c0a-\U00011c36\U00011c38-\U00011c40\U00011c50-\U00011c59\U00011c72-\U00011c8f\U00011c92-\U00011ca7\U00011ca9-\U00011cb6\U00011d00-\U00011d06\U00011d08-\U00011d09\U00011d0b-\U00011d36\U00011d3a\U00011d3c-\U00011d3d\U00011d3f-\U00011d47\U00011d50-\U00011d59\U00011d60-\U00011d65\U00011d67-\U00011d68\U00011d6a-\U00011d8e\U00011d90-\U00011d91\U00011d93-\U00011d98\U00011da0-\U00011da9\U00011ee0-\U00011ef6\U00012000-\U00012399\U00012400-\U0001246e\U00012480-\U00012543\U00013000-\U0001342e\U00014400-\U00014646\U00016800-\U00016a38\U00016a40-\U00016a5e\U00016a60-\U00016a69\U00016ad0-\U00016aed\U00016af0-\U00016af4\U00016b00-\U00016b36\U00016b40-\U00016b43\U00016b50-\U00016b59\U00016b63-\U00016b77\U00016b7d-\U00016b8f\U00016e40-\U00016e7f\U00016f00-\U00016f44\U00016f50-\U00016f7e\U00016f8f-\U00016f9f\U00016fe0-\U00016fe1\U00017000-\U000187f1\U00018800-\U00018af2\U0001b000-\U0001b11e\U0001b170-\U0001b2fb\U0001bc00-\U0001bc6a\U0001bc70-\U0001bc7c\U0001bc80-\U0001bc88\U0001bc90-\U0001bc99\U0001bc9d-\U0001bc9e\U0001d165-\U0001d169\U0001d16d-\U0001d172\U0001d17b-\U0001d182\U0001d185-\U0001d18b\U0001d1aa-\U0001d1ad\U0001d242-\U0001d244\U0001d400-\U0001d454\U0001d456-\U0001d49c\U0001d49e-\U0001d49f\U0001d4a2\U0001d4a5-\U0001d4a6\U0001d4a9-\U0001d4ac\U0001d4ae-\U0001d4b9\U0001d4bb\U0001d4bd-\U0001d4c3\U0001d4c5-\U0001d505\U0001d507-\U0001d50a\U0001d50d-\U0001d514\U0001d516-\U0001d51c\U0001d51e-\U0001d539\U0001d53b-\U0001d53e\U0001d540-\U0001d544\U0001d546\U0001d54a-\U0001d550\U0001d552-\U0001d6a5\U0001d6a8-\U0001d6c0\U0001d6c2-\U0001d6da\U0001d6dc-\U0001d6fa\U0001d6fc-\U0001d714\U0001d716-\U0001d734\U0001d736-\U0001d74e\U0001d750-\U0001d76e\U0001d770-\U0001d788\U0001d78a-\U0001d7a8\U0001d7aa-\U0001d7c2\U0001d7c4-\U0001d7cb\U0001d7ce-\U0001d7ff\U0001da00-\U0001da36\U0001da3b-\U0001da6c\U0001da75\U0001da84\U0001da9b-\U0001da9f\U0001daa1-\U0001daaf\U0001e000-\U0001e006\U0001e008-\U0001e018\U0001e01b-\U0001e021\U0001e023-\U0001e024\U0001e026-\U0001e02a\U0001e800-\U0001e8c4\U0001e8d0-\U0001e8d6\U0001e900-\U0001e94a\U0001e950-\U0001e959\U0001ee00-\U0001ee03\U0001ee05-\U0001ee1f\U0001ee21-\U0001ee22\U0001ee24\U0001ee27\U0001ee29-\U0001ee32\U0001ee34-\U0001ee37\U0001ee39\U0001ee3b\U0001ee42\U0001ee47\U0001ee49\U0001ee4b\U0001ee4d-\U0001ee4f\U0001ee51-\U0001ee52\U0001ee54\U0001ee57\U0001ee59\U0001ee5b\U0001ee5d\U0001ee5f\U0001ee61-\U0001ee62\U0001ee64\U0001ee67-\U0001ee6a\U0001ee6c-\U0001ee72\U0001ee74-\U0001ee77\U0001ee79-\U0001ee7c\U0001ee7e\U0001ee80-\U0001ee89\U0001ee8b-\U0001ee9b\U0001eea1-\U0001eea3\U0001eea5-\U0001eea9\U0001eeab-\U0001eebb\U00020000-\U0002a6d6\U0002a700-\U0002b734\U0002b740-\U0002b81d\U0002b820-\U0002cea1\U0002ceb0-\U0002ebe0\U0002f800-\U0002fa1d\U000e0100-\U000e01ef'
|
| 75 |
+
|
| 76 |
+
xid_start = 'A-Z_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376-\u0377\u037b-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e-\u066f\u0671-\u06d3\u06d5\u06e5-\u06e6\u06ee-\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4-\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u09fc\u0a05-\u0a0a\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0-\u0ae1\u0af9\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32-\u0b33\u0b35-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60-\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0-\u0ce1\u0cf1-\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e40-\u0e46\u0e81-\u0e82\u0e84\u0e87-\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa-\u0eab\u0ead-\u0eb0\u0eb2\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065-\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae-\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5-\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a-\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7b9\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd-\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5-\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufbb1\ufbd3-\ufc5d\ufc64-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdf9\ufe71\ufe73\ufe77\ufe79\ufe7b\ufe7d\ufe7f-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uff9d\uffa0-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc\U00010000-\U0001000b\U0001000d-\U00010026\U00010028-\U0001003a\U0001003c-\U0001003d\U0001003f-\U0001004d\U00010050-\U0001005d\U00010080-\U000100fa\U00010140-\U00010174\U00010280-\U0001029c\U000102a0-\U000102d0\U00010300-\U0001031f\U0001032d-\U0001034a\U00010350-\U00010375\U00010380-\U0001039d\U000103a0-\U000103c3\U000103c8-\U000103cf\U000103d1-\U000103d5\U00010400-\U0001049d\U000104b0-\U000104d3\U000104d8-\U000104fb\U00010500-\U00010527\U00010530-\U00010563\U00010600-\U00010736\U00010740-\U00010755\U00010760-\U00010767\U00010800-\U00010805\U00010808\U0001080a-\U00010835\U00010837-\U00010838\U0001083c\U0001083f-\U00010855\U00010860-\U00010876\U00010880-\U0001089e\U000108e0-\U000108f2\U000108f4-\U000108f5\U00010900-\U00010915\U00010920-\U00010939\U00010980-\U000109b7\U000109be-\U000109bf\U00010a00\U00010a10-\U00010a13\U00010a15-\U00010a17\U00010a19-\U00010a35\U00010a60-\U00010a7c\U00010a80-\U00010a9c\U00010ac0-\U00010ac7\U00010ac9-\U00010ae4\U00010b00-\U00010b35\U00010b40-\U00010b55\U00010b60-\U00010b72\U00010b80-\U00010b91\U00010c00-\U00010c48\U00010c80-\U00010cb2\U00010cc0-\U00010cf2\U00010d00-\U00010d23\U00010f00-\U00010f1c\U00010f27\U00010f30-\U00010f45\U00011003-\U00011037\U00011083-\U000110af\U000110d0-\U000110e8\U00011103-\U00011126\U00011144\U00011150-\U00011172\U00011176\U00011183-\U000111b2\U000111c1-\U000111c4\U000111da\U000111dc\U00011200-\U00011211\U00011213-\U0001122b\U00011280-\U00011286\U00011288\U0001128a-\U0001128d\U0001128f-\U0001129d\U0001129f-\U000112a8\U000112b0-\U000112de\U00011305-\U0001130c\U0001130f-\U00011310\U00011313-\U00011328\U0001132a-\U00011330\U00011332-\U00011333\U00011335-\U00011339\U0001133d\U00011350\U0001135d-\U00011361\U00011400-\U00011434\U00011447-\U0001144a\U00011480-\U000114af\U000114c4-\U000114c5\U000114c7\U00011580-\U000115ae\U000115d8-\U000115db\U00011600-\U0001162f\U00011644\U00011680-\U000116aa\U00011700-\U0001171a\U00011800-\U0001182b\U000118a0-\U000118df\U000118ff\U00011a00\U00011a0b-\U00011a32\U00011a3a\U00011a50\U00011a5c-\U00011a83\U00011a86-\U00011a89\U00011a9d\U00011ac0-\U00011af8\U00011c00-\U00011c08\U00011c0a-\U00011c2e\U00011c40\U00011c72-\U00011c8f\U00011d00-\U00011d06\U00011d08-\U00011d09\U00011d0b-\U00011d30\U00011d46\U00011d60-\U00011d65\U00011d67-\U00011d68\U00011d6a-\U00011d89\U00011d98\U00011ee0-\U00011ef2\U00012000-\U00012399\U00012400-\U0001246e\U00012480-\U00012543\U00013000-\U0001342e\U00014400-\U00014646\U00016800-\U00016a38\U00016a40-\U00016a5e\U00016ad0-\U00016aed\U00016b00-\U00016b2f\U00016b40-\U00016b43\U00016b63-\U00016b77\U00016b7d-\U00016b8f\U00016e40-\U00016e7f\U00016f00-\U00016f44\U00016f50\U00016f93-\U00016f9f\U00016fe0-\U00016fe1\U00017000-\U000187f1\U00018800-\U00018af2\U0001b000-\U0001b11e\U0001b170-\U0001b2fb\U0001bc00-\U0001bc6a\U0001bc70-\U0001bc7c\U0001bc80-\U0001bc88\U0001bc90-\U0001bc99\U0001d400-\U0001d454\U0001d456-\U0001d49c\U0001d49e-\U0001d49f\U0001d4a2\U0001d4a5-\U0001d4a6\U0001d4a9-\U0001d4ac\U0001d4ae-\U0001d4b9\U0001d4bb\U0001d4bd-\U0001d4c3\U0001d4c5-\U0001d505\U0001d507-\U0001d50a\U0001d50d-\U0001d514\U0001d516-\U0001d51c\U0001d51e-\U0001d539\U0001d53b-\U0001d53e\U0001d540-\U0001d544\U0001d546\U0001d54a-\U0001d550\U0001d552-\U0001d6a5\U0001d6a8-\U0001d6c0\U0001d6c2-\U0001d6da\U0001d6dc-\U0001d6fa\U0001d6fc-\U0001d714\U0001d716-\U0001d734\U0001d736-\U0001d74e\U0001d750-\U0001d76e\U0001d770-\U0001d788\U0001d78a-\U0001d7a8\U0001d7aa-\U0001d7c2\U0001d7c4-\U0001d7cb\U0001e800-\U0001e8c4\U0001e900-\U0001e943\U0001ee00-\U0001ee03\U0001ee05-\U0001ee1f\U0001ee21-\U0001ee22\U0001ee24\U0001ee27\U0001ee29-\U0001ee32\U0001ee34-\U0001ee37\U0001ee39\U0001ee3b\U0001ee42\U0001ee47\U0001ee49\U0001ee4b\U0001ee4d-\U0001ee4f\U0001ee51-\U0001ee52\U0001ee54\U0001ee57\U0001ee59\U0001ee5b\U0001ee5d\U0001ee5f\U0001ee61-\U0001ee62\U0001ee64\U0001ee67-\U0001ee6a\U0001ee6c-\U0001ee72\U0001ee74-\U0001ee77\U0001ee79-\U0001ee7c\U0001ee7e\U0001ee80-\U0001ee89\U0001ee8b-\U0001ee9b\U0001eea1-\U0001eea3\U0001eea5-\U0001eea9\U0001eeab-\U0001eebb\U00020000-\U0002a6d6\U0002a700-\U0002b734\U0002b740-\U0002b81d\U0002b820-\U0002cea1\U0002ceb0-\U0002ebe0\U0002f800-\U0002fa1d'
|
| 77 |
+
|
| 78 |
+
cats = ['Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu', 'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf', 'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs']
|
| 79 |
+
|
| 80 |
+
# Generated from unidata 11.0.0
|
| 81 |
+
|
| 82 |
+
def combine(*args):
|
| 83 |
+
return ''.join(globals()[cat] for cat in args)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def allexcept(*args):
|
| 87 |
+
newcats = cats[:]
|
| 88 |
+
for arg in args:
|
| 89 |
+
newcats.remove(arg)
|
| 90 |
+
return ''.join(globals()[cat] for cat in newcats)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def _handle_runs(char_list): # pragma: no cover
|
| 94 |
+
buf = []
|
| 95 |
+
for c in char_list:
|
| 96 |
+
if len(c) == 1:
|
| 97 |
+
if buf and buf[-1][1] == chr(ord(c)-1):
|
| 98 |
+
buf[-1] = (buf[-1][0], c)
|
| 99 |
+
else:
|
| 100 |
+
buf.append((c, c))
|
| 101 |
+
else:
|
| 102 |
+
buf.append((c, c))
|
| 103 |
+
for a, b in buf:
|
| 104 |
+
if a == b:
|
| 105 |
+
yield a
|
| 106 |
+
else:
|
| 107 |
+
yield f'{a}-{b}'
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
if __name__ == '__main__': # pragma: no cover
|
| 111 |
+
import unicodedata
|
| 112 |
+
|
| 113 |
+
categories = {'xid_start': [], 'xid_continue': []}
|
| 114 |
+
|
| 115 |
+
with open(__file__, encoding='utf-8') as fp:
|
| 116 |
+
content = fp.read()
|
| 117 |
+
|
| 118 |
+
header = content[:content.find('Cc =')]
|
| 119 |
+
footer = content[content.find("def combine("):]
|
| 120 |
+
|
| 121 |
+
for code in range(0x110000):
|
| 122 |
+
c = chr(code)
|
| 123 |
+
cat = unicodedata.category(c)
|
| 124 |
+
if ord(c) == 0xdc00:
|
| 125 |
+
# Hack to avoid combining this combining with the preceding high
|
| 126 |
+
# surrogate, 0xdbff, when doing a repr.
|
| 127 |
+
c = '\\' + c
|
| 128 |
+
elif ord(c) in (0x2d, 0x5b, 0x5c, 0x5d, 0x5e):
|
| 129 |
+
# Escape regex metachars.
|
| 130 |
+
c = '\\' + c
|
| 131 |
+
categories.setdefault(cat, []).append(c)
|
| 132 |
+
# XID_START and XID_CONTINUE are special categories used for matching
|
| 133 |
+
# identifiers in Python 3.
|
| 134 |
+
if c.isidentifier():
|
| 135 |
+
categories['xid_start'].append(c)
|
| 136 |
+
if ('a' + c).isidentifier():
|
| 137 |
+
categories['xid_continue'].append(c)
|
| 138 |
+
|
| 139 |
+
with open(__file__, 'w', encoding='utf-8') as fp:
|
| 140 |
+
fp.write(header)
|
| 141 |
+
|
| 142 |
+
for cat in sorted(categories):
|
| 143 |
+
val = ''.join(_handle_runs(categories[cat]))
|
| 144 |
+
fp.write(f'{cat} = {val!a}\n\n')
|
| 145 |
+
|
| 146 |
+
cats = sorted(categories)
|
| 147 |
+
cats.remove('xid_start')
|
| 148 |
+
cats.remove('xid_continue')
|
| 149 |
+
fp.write(f'cats = {cats!r}\n\n')
|
| 150 |
+
|
| 151 |
+
fp.write(f'# Generated from unidata {unicodedata.unidata_version}\n\n')
|
| 152 |
+
|
| 153 |
+
fp.write(footer)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/pygments/util.py
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
pygments.util
|
| 3 |
+
~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Utility functions.
|
| 6 |
+
|
| 7 |
+
:copyright: Copyright 2006-present by the Pygments team, see AUTHORS.
|
| 8 |
+
:license: BSD, see LICENSE for details.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import re
|
| 12 |
+
from io import TextIOWrapper
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
split_path_re = re.compile(r'[/\\ ]')
|
| 16 |
+
doctype_lookup_re = re.compile(r'''
|
| 17 |
+
<!DOCTYPE\s+(
|
| 18 |
+
[a-zA-Z_][a-zA-Z0-9]*
|
| 19 |
+
(?: \s+ # optional in HTML5
|
| 20 |
+
[a-zA-Z_][a-zA-Z0-9]*\s+
|
| 21 |
+
"[^"]*")?
|
| 22 |
+
)
|
| 23 |
+
[^>]*>
|
| 24 |
+
''', re.DOTALL | re.MULTILINE | re.VERBOSE)
|
| 25 |
+
tag_re = re.compile(r'<(.+?)(\s.*?)?>.*?</.+?>',
|
| 26 |
+
re.IGNORECASE | re.DOTALL | re.MULTILINE)
|
| 27 |
+
xml_decl_re = re.compile(r'\s*<\?xml[^>]*\?>', re.I)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class ClassNotFound(ValueError):
|
| 31 |
+
"""Raised if one of the lookup functions didn't find a matching class."""
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class OptionError(Exception):
|
| 35 |
+
"""
|
| 36 |
+
This exception will be raised by all option processing functions if
|
| 37 |
+
the type or value of the argument is not correct.
|
| 38 |
+
"""
|
| 39 |
+
|
| 40 |
+
def get_choice_opt(options, optname, allowed, default=None, normcase=False):
|
| 41 |
+
"""
|
| 42 |
+
If the key `optname` from the dictionary is not in the sequence
|
| 43 |
+
`allowed`, raise an error, otherwise return it.
|
| 44 |
+
"""
|
| 45 |
+
string = options.get(optname, default)
|
| 46 |
+
if normcase:
|
| 47 |
+
string = string.lower()
|
| 48 |
+
if string not in allowed:
|
| 49 |
+
raise OptionError('Value for option {} must be one of {}'.format(optname, ', '.join(map(str, allowed))))
|
| 50 |
+
return string
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def get_bool_opt(options, optname, default=None):
|
| 54 |
+
"""
|
| 55 |
+
Intuitively, this is `options.get(optname, default)`, but restricted to
|
| 56 |
+
Boolean value. The Booleans can be represented as string, in order to accept
|
| 57 |
+
Boolean value from the command line arguments. If the key `optname` is
|
| 58 |
+
present in the dictionary `options` and is not associated with a Boolean,
|
| 59 |
+
raise an `OptionError`. If it is absent, `default` is returned instead.
|
| 60 |
+
|
| 61 |
+
The valid string values for ``True`` are ``1``, ``yes``, ``true`` and
|
| 62 |
+
``on``, the ones for ``False`` are ``0``, ``no``, ``false`` and ``off``
|
| 63 |
+
(matched case-insensitively).
|
| 64 |
+
"""
|
| 65 |
+
string = options.get(optname, default)
|
| 66 |
+
if isinstance(string, bool):
|
| 67 |
+
return string
|
| 68 |
+
elif isinstance(string, int):
|
| 69 |
+
return bool(string)
|
| 70 |
+
elif not isinstance(string, str):
|
| 71 |
+
raise OptionError(f'Invalid type {string!r} for option {optname}; use '
|
| 72 |
+
'1/0, yes/no, true/false, on/off')
|
| 73 |
+
elif string.lower() in ('1', 'yes', 'true', 'on'):
|
| 74 |
+
return True
|
| 75 |
+
elif string.lower() in ('0', 'no', 'false', 'off'):
|
| 76 |
+
return False
|
| 77 |
+
else:
|
| 78 |
+
raise OptionError(f'Invalid value {string!r} for option {optname}; use '
|
| 79 |
+
'1/0, yes/no, true/false, on/off')
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def get_int_opt(options, optname, default=None):
|
| 83 |
+
"""As :func:`get_bool_opt`, but interpret the value as an integer."""
|
| 84 |
+
string = options.get(optname, default)
|
| 85 |
+
try:
|
| 86 |
+
return int(string)
|
| 87 |
+
except TypeError:
|
| 88 |
+
raise OptionError(f'Invalid type {string!r} for option {optname}; you '
|
| 89 |
+
'must give an integer value')
|
| 90 |
+
except ValueError:
|
| 91 |
+
raise OptionError(f'Invalid value {string!r} for option {optname}; you '
|
| 92 |
+
'must give an integer value')
|
| 93 |
+
|
| 94 |
+
def get_list_opt(options, optname, default=None):
|
| 95 |
+
"""
|
| 96 |
+
If the key `optname` from the dictionary `options` is a string,
|
| 97 |
+
split it at whitespace and return it. If it is already a list
|
| 98 |
+
or a tuple, it is returned as a list.
|
| 99 |
+
"""
|
| 100 |
+
val = options.get(optname, default)
|
| 101 |
+
if isinstance(val, str):
|
| 102 |
+
return val.split()
|
| 103 |
+
elif isinstance(val, (list, tuple)):
|
| 104 |
+
return list(val)
|
| 105 |
+
else:
|
| 106 |
+
raise OptionError(f'Invalid type {val!r} for option {optname}; you '
|
| 107 |
+
'must give a list value')
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def docstring_headline(obj):
|
| 111 |
+
if not obj.__doc__:
|
| 112 |
+
return ''
|
| 113 |
+
res = []
|
| 114 |
+
for line in obj.__doc__.strip().splitlines():
|
| 115 |
+
if line.strip():
|
| 116 |
+
res.append(" " + line.strip())
|
| 117 |
+
else:
|
| 118 |
+
break
|
| 119 |
+
return ''.join(res).lstrip()
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def make_analysator(f):
|
| 123 |
+
"""Return a static text analyser function that returns float values."""
|
| 124 |
+
def text_analyse(text):
|
| 125 |
+
try:
|
| 126 |
+
rv = f(text)
|
| 127 |
+
except Exception:
|
| 128 |
+
return 0.0
|
| 129 |
+
if not rv:
|
| 130 |
+
return 0.0
|
| 131 |
+
try:
|
| 132 |
+
return min(1.0, max(0.0, float(rv)))
|
| 133 |
+
except (ValueError, TypeError):
|
| 134 |
+
return 0.0
|
| 135 |
+
text_analyse.__doc__ = f.__doc__
|
| 136 |
+
return staticmethod(text_analyse)
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def shebang_matches(text, regex):
|
| 140 |
+
r"""Check if the given regular expression matches the last part of the
|
| 141 |
+
shebang if one exists.
|
| 142 |
+
|
| 143 |
+
>>> from pygments.util import shebang_matches
|
| 144 |
+
>>> shebang_matches('#!/usr/bin/env python', r'python(2\.\d)?')
|
| 145 |
+
True
|
| 146 |
+
>>> shebang_matches('#!/usr/bin/python2.4', r'python(2\.\d)?')
|
| 147 |
+
True
|
| 148 |
+
>>> shebang_matches('#!/usr/bin/python-ruby', r'python(2\.\d)?')
|
| 149 |
+
False
|
| 150 |
+
>>> shebang_matches('#!/usr/bin/python/ruby', r'python(2\.\d)?')
|
| 151 |
+
False
|
| 152 |
+
>>> shebang_matches('#!/usr/bin/startsomethingwith python',
|
| 153 |
+
... r'python(2\.\d)?')
|
| 154 |
+
True
|
| 155 |
+
|
| 156 |
+
It also checks for common windows executable file extensions::
|
| 157 |
+
|
| 158 |
+
>>> shebang_matches('#!C:\\Python2.4\\Python.exe', r'python(2\.\d)?')
|
| 159 |
+
True
|
| 160 |
+
|
| 161 |
+
Parameters (``'-f'`` or ``'--foo'`` are ignored so ``'perl'`` does
|
| 162 |
+
the same as ``'perl -e'``)
|
| 163 |
+
|
| 164 |
+
Note that this method automatically searches the whole string (eg:
|
| 165 |
+
the regular expression is wrapped in ``'^$'``)
|
| 166 |
+
"""
|
| 167 |
+
index = text.find('\n')
|
| 168 |
+
if index >= 0:
|
| 169 |
+
first_line = text[:index].lower()
|
| 170 |
+
else:
|
| 171 |
+
first_line = text.lower()
|
| 172 |
+
if first_line.startswith('#!'):
|
| 173 |
+
try:
|
| 174 |
+
found = [x for x in split_path_re.split(first_line[2:].strip())
|
| 175 |
+
if x and not x.startswith('-')][-1]
|
| 176 |
+
except IndexError:
|
| 177 |
+
return False
|
| 178 |
+
regex = re.compile(rf'^{regex}(\.(exe|cmd|bat|bin))?$', re.IGNORECASE)
|
| 179 |
+
if regex.search(found) is not None:
|
| 180 |
+
return True
|
| 181 |
+
return False
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
def doctype_matches(text, regex):
|
| 185 |
+
"""Check if the doctype matches a regular expression (if present).
|
| 186 |
+
|
| 187 |
+
Note that this method only checks the first part of a DOCTYPE.
|
| 188 |
+
eg: 'html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"'
|
| 189 |
+
"""
|
| 190 |
+
m = doctype_lookup_re.search(text)
|
| 191 |
+
if m is None:
|
| 192 |
+
return False
|
| 193 |
+
doctype = m.group(1)
|
| 194 |
+
return re.compile(regex, re.I).match(doctype.strip()) is not None
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
def html_doctype_matches(text):
|
| 198 |
+
"""Check if the file looks like it has a html doctype."""
|
| 199 |
+
return doctype_matches(text, r'html')
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
_looks_like_xml_cache = {}
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
def looks_like_xml(text):
|
| 206 |
+
"""Check if a doctype exists or if we have some tags."""
|
| 207 |
+
if xml_decl_re.match(text):
|
| 208 |
+
return True
|
| 209 |
+
key = hash(text)
|
| 210 |
+
try:
|
| 211 |
+
return _looks_like_xml_cache[key]
|
| 212 |
+
except KeyError:
|
| 213 |
+
m = doctype_lookup_re.search(text)
|
| 214 |
+
if m is not None:
|
| 215 |
+
return True
|
| 216 |
+
rv = tag_re.search(text[:1000]) is not None
|
| 217 |
+
_looks_like_xml_cache[key] = rv
|
| 218 |
+
return rv
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def surrogatepair(c):
|
| 222 |
+
"""Given a unicode character code with length greater than 16 bits,
|
| 223 |
+
return the two 16 bit surrogate pair.
|
| 224 |
+
"""
|
| 225 |
+
# From example D28 of:
|
| 226 |
+
# http://www.unicode.org/book/ch03.pdf
|
| 227 |
+
return (0xd7c0 + (c >> 10), (0xdc00 + (c & 0x3ff)))
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
def format_lines(var_name, seq, raw=False, indent_level=0):
|
| 231 |
+
"""Formats a sequence of strings for output."""
|
| 232 |
+
lines = []
|
| 233 |
+
base_indent = ' ' * indent_level * 4
|
| 234 |
+
inner_indent = ' ' * (indent_level + 1) * 4
|
| 235 |
+
lines.append(base_indent + var_name + ' = (')
|
| 236 |
+
if raw:
|
| 237 |
+
# These should be preformatted reprs of, say, tuples.
|
| 238 |
+
for i in seq:
|
| 239 |
+
lines.append(inner_indent + i + ',')
|
| 240 |
+
else:
|
| 241 |
+
for i in seq:
|
| 242 |
+
# Force use of single quotes
|
| 243 |
+
r = repr(i + '"')
|
| 244 |
+
lines.append(inner_indent + r[:-2] + r[-1] + ',')
|
| 245 |
+
lines.append(base_indent + ')')
|
| 246 |
+
return '\n'.join(lines)
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
def duplicates_removed(it, already_seen=()):
|
| 250 |
+
"""
|
| 251 |
+
Returns a list with duplicates removed from the iterable `it`.
|
| 252 |
+
|
| 253 |
+
Order is preserved.
|
| 254 |
+
"""
|
| 255 |
+
lst = []
|
| 256 |
+
seen = set()
|
| 257 |
+
for i in it:
|
| 258 |
+
if i in seen or i in already_seen:
|
| 259 |
+
continue
|
| 260 |
+
lst.append(i)
|
| 261 |
+
seen.add(i)
|
| 262 |
+
return lst
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
class Future:
|
| 266 |
+
"""Generic class to defer some work.
|
| 267 |
+
|
| 268 |
+
Handled specially in RegexLexerMeta, to support regex string construction at
|
| 269 |
+
first use.
|
| 270 |
+
"""
|
| 271 |
+
def get(self):
|
| 272 |
+
raise NotImplementedError
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def guess_decode(text):
|
| 276 |
+
"""Decode *text* with guessed encoding.
|
| 277 |
+
|
| 278 |
+
First try UTF-8; this should fail for non-UTF-8 encodings.
|
| 279 |
+
Then try the preferred locale encoding.
|
| 280 |
+
Fall back to latin-1, which always works.
|
| 281 |
+
"""
|
| 282 |
+
try:
|
| 283 |
+
text = text.decode('utf-8')
|
| 284 |
+
return text, 'utf-8'
|
| 285 |
+
except UnicodeDecodeError:
|
| 286 |
+
try:
|
| 287 |
+
import locale
|
| 288 |
+
prefencoding = locale.getpreferredencoding()
|
| 289 |
+
text = text.decode(prefencoding)
|
| 290 |
+
return text, prefencoding
|
| 291 |
+
except (UnicodeDecodeError, LookupError):
|
| 292 |
+
text = text.decode('latin1')
|
| 293 |
+
return text, 'latin1'
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
def guess_decode_from_terminal(text, term):
|
| 297 |
+
"""Decode *text* coming from terminal *term*.
|
| 298 |
+
|
| 299 |
+
First try the terminal encoding, if given.
|
| 300 |
+
Then try UTF-8. Then try the preferred locale encoding.
|
| 301 |
+
Fall back to latin-1, which always works.
|
| 302 |
+
"""
|
| 303 |
+
if getattr(term, 'encoding', None):
|
| 304 |
+
try:
|
| 305 |
+
text = text.decode(term.encoding)
|
| 306 |
+
except UnicodeDecodeError:
|
| 307 |
+
pass
|
| 308 |
+
else:
|
| 309 |
+
return text, term.encoding
|
| 310 |
+
return guess_decode(text)
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
def terminal_encoding(term):
|
| 314 |
+
"""Return our best guess of encoding for the given *term*."""
|
| 315 |
+
if getattr(term, 'encoding', None):
|
| 316 |
+
return term.encoding
|
| 317 |
+
import locale
|
| 318 |
+
return locale.getpreferredencoding()
|
| 319 |
+
|
| 320 |
+
|
| 321 |
+
class UnclosingTextIOWrapper(TextIOWrapper):
|
| 322 |
+
# Don't close underlying buffer on destruction.
|
| 323 |
+
def close(self):
|
| 324 |
+
self.flush()
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/shellingham/posix/__init__.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import re
|
| 3 |
+
|
| 4 |
+
from .._core import SHELL_NAMES, ShellDetectionFailure
|
| 5 |
+
from . import proc, ps
|
| 6 |
+
|
| 7 |
+
# Based on QEMU docs: https://www.qemu.org/docs/master/user/main.html
|
| 8 |
+
QEMU_BIN_REGEX = re.compile(
|
| 9 |
+
r"""qemu-
|
| 10 |
+
(alpha
|
| 11 |
+
|armeb
|
| 12 |
+
|arm
|
| 13 |
+
|m68k
|
| 14 |
+
|cris
|
| 15 |
+
|i386
|
| 16 |
+
|x86_64
|
| 17 |
+
|microblaze
|
| 18 |
+
|mips
|
| 19 |
+
|mipsel
|
| 20 |
+
|mips64
|
| 21 |
+
|mips64el
|
| 22 |
+
|mipsn32
|
| 23 |
+
|mipsn32el
|
| 24 |
+
|nios2
|
| 25 |
+
|ppc64
|
| 26 |
+
|ppc
|
| 27 |
+
|sh4eb
|
| 28 |
+
|sh4
|
| 29 |
+
|sparc
|
| 30 |
+
|sparc32plus
|
| 31 |
+
|sparc64
|
| 32 |
+
)""",
|
| 33 |
+
re.VERBOSE,
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def _iter_process_parents(pid, max_depth=10):
|
| 38 |
+
"""Select a way to obtain process information from the system.
|
| 39 |
+
|
| 40 |
+
* `/proc` is used if supported.
|
| 41 |
+
* The system `ps` utility is used as a fallback option.
|
| 42 |
+
"""
|
| 43 |
+
for impl in (proc, ps):
|
| 44 |
+
try:
|
| 45 |
+
iterator = impl.iter_process_parents(pid, max_depth)
|
| 46 |
+
except EnvironmentError:
|
| 47 |
+
continue
|
| 48 |
+
return iterator
|
| 49 |
+
raise ShellDetectionFailure("compatible proc fs or ps utility is required")
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def _get_login_shell(proc_cmd):
|
| 53 |
+
"""Form shell information from SHELL environ if possible."""
|
| 54 |
+
login_shell = os.environ.get("SHELL", "")
|
| 55 |
+
if login_shell:
|
| 56 |
+
proc_cmd = login_shell
|
| 57 |
+
else:
|
| 58 |
+
proc_cmd = proc_cmd[1:]
|
| 59 |
+
return (os.path.basename(proc_cmd).lower(), proc_cmd)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
_INTERPRETER_SHELL_NAMES = [
|
| 63 |
+
(re.compile(r"^python(\d+(\.\d+)?)?$"), {"xonsh"}),
|
| 64 |
+
]
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def _get_interpreter_shell(proc_name, proc_args):
|
| 68 |
+
"""Get shell invoked via an interpreter.
|
| 69 |
+
|
| 70 |
+
Some shells are implemented on, and invoked with an interpreter, e.g. xonsh
|
| 71 |
+
is commonly executed with an executable Python script. This detects what
|
| 72 |
+
script the interpreter is actually running, and check whether that looks
|
| 73 |
+
like a shell.
|
| 74 |
+
|
| 75 |
+
See sarugaku/shellingham#26 for rational.
|
| 76 |
+
"""
|
| 77 |
+
for pattern, shell_names in _INTERPRETER_SHELL_NAMES:
|
| 78 |
+
if not pattern.match(proc_name):
|
| 79 |
+
continue
|
| 80 |
+
for arg in proc_args:
|
| 81 |
+
name = os.path.basename(arg).lower()
|
| 82 |
+
if os.path.isfile(arg) and name in shell_names:
|
| 83 |
+
return (name, arg)
|
| 84 |
+
return None
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def _get_shell(cmd, *args):
|
| 88 |
+
if cmd.startswith("-"): # Login shell! Let's use this.
|
| 89 |
+
return _get_login_shell(cmd)
|
| 90 |
+
name = os.path.basename(cmd).lower()
|
| 91 |
+
if name == "rosetta" or QEMU_BIN_REGEX.fullmatch(name):
|
| 92 |
+
# If the current process is Rosetta or QEMU, this likely is a
|
| 93 |
+
# containerized process. Parse out the actual command instead.
|
| 94 |
+
cmd = args[0]
|
| 95 |
+
args = args[1:]
|
| 96 |
+
name = os.path.basename(cmd).lower()
|
| 97 |
+
if name in SHELL_NAMES: # Command looks like a shell.
|
| 98 |
+
return (name, cmd)
|
| 99 |
+
shell = _get_interpreter_shell(name, args)
|
| 100 |
+
if shell:
|
| 101 |
+
return shell
|
| 102 |
+
return None
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def get_shell(pid=None, max_depth=10):
|
| 106 |
+
"""Get the shell that the supplied pid or os.getpid() is running in."""
|
| 107 |
+
pid = str(pid or os.getpid())
|
| 108 |
+
for proc_args, _, _ in _iter_process_parents(pid, max_depth):
|
| 109 |
+
shell = _get_shell(*proc_args)
|
| 110 |
+
if shell:
|
| 111 |
+
return shell
|
| 112 |
+
return None
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/shellingham/posix/ps.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import errno
|
| 2 |
+
import subprocess
|
| 3 |
+
import sys
|
| 4 |
+
|
| 5 |
+
from ._core import Process
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class PsNotAvailable(EnvironmentError):
|
| 9 |
+
pass
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def iter_process_parents(pid, max_depth=10):
|
| 13 |
+
"""Try to look up the process tree via the output of `ps`."""
|
| 14 |
+
try:
|
| 15 |
+
cmd = ["ps", "-ww", "-o", "pid=", "-o", "ppid=", "-o", "args="]
|
| 16 |
+
output = subprocess.check_output(cmd)
|
| 17 |
+
except OSError as e: # Python 2-compatible FileNotFoundError.
|
| 18 |
+
if e.errno != errno.ENOENT:
|
| 19 |
+
raise
|
| 20 |
+
raise PsNotAvailable("ps not found")
|
| 21 |
+
except subprocess.CalledProcessError as e:
|
| 22 |
+
# `ps` can return 1 if the process list is completely empty.
|
| 23 |
+
# (sarugaku/shellingham#15)
|
| 24 |
+
if not e.output.strip():
|
| 25 |
+
return
|
| 26 |
+
raise
|
| 27 |
+
if not isinstance(output, str):
|
| 28 |
+
encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
|
| 29 |
+
output = output.decode(encoding)
|
| 30 |
+
|
| 31 |
+
processes_mapping = {}
|
| 32 |
+
for line in output.split("\n"):
|
| 33 |
+
try:
|
| 34 |
+
_pid, ppid, args = line.strip().split(None, 2)
|
| 35 |
+
# XXX: This is not right, but we are really out of options.
|
| 36 |
+
# ps does not offer a sane way to decode the argument display,
|
| 37 |
+
# and this is "Good Enough" for obtaining shell names. Hopefully
|
| 38 |
+
# people don't name their shell with a space, or have something
|
| 39 |
+
# like "/usr/bin/xonsh is uber". (sarugaku/shellingham#14)
|
| 40 |
+
args = tuple(a.strip() for a in args.split(" "))
|
| 41 |
+
except ValueError:
|
| 42 |
+
continue
|
| 43 |
+
processes_mapping[_pid] = Process(args=args, pid=_pid, ppid=ppid)
|
| 44 |
+
|
| 45 |
+
for _ in range(max_depth):
|
| 46 |
+
try:
|
| 47 |
+
process = processes_mapping[pid]
|
| 48 |
+
except KeyError:
|
| 49 |
+
return
|
| 50 |
+
yield process
|
| 51 |
+
pid = process.ppid
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/aria/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
from typing import TYPE_CHECKING
|
| 15 |
+
|
| 16 |
+
from ...utils import _LazyModule
|
| 17 |
+
from ...utils.import_utils import define_import_structure
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
if TYPE_CHECKING:
|
| 21 |
+
from .configuration_aria import *
|
| 22 |
+
from .image_processing_aria import *
|
| 23 |
+
from .image_processing_pil_aria import *
|
| 24 |
+
from .modeling_aria import *
|
| 25 |
+
from .processing_aria import *
|
| 26 |
+
|
| 27 |
+
else:
|
| 28 |
+
import sys
|
| 29 |
+
|
| 30 |
+
_file = globals()["__file__"]
|
| 31 |
+
sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/aria/modular_aria.py
ADDED
|
@@ -0,0 +1,1156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 The Rhymes-AI Teams Authors and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
import torch
|
| 15 |
+
from huggingface_hub.dataclasses import strict
|
| 16 |
+
from torch import nn
|
| 17 |
+
from torchvision.transforms.v2 import functional as tvF
|
| 18 |
+
|
| 19 |
+
from ... import initialization as init
|
| 20 |
+
from ...activations import ACT2FN
|
| 21 |
+
from ...cache_utils import Cache
|
| 22 |
+
from ...configuration_utils import PreTrainedConfig
|
| 23 |
+
from ...image_processing_backends import TorchvisionBackend
|
| 24 |
+
from ...image_processing_utils import BatchFeature, get_patch_output_size, select_best_resolution
|
| 25 |
+
from ...image_transforms import divide_to_patches
|
| 26 |
+
from ...image_utils import (
|
| 27 |
+
ChannelDimension,
|
| 28 |
+
ImageInput,
|
| 29 |
+
PILImageResampling,
|
| 30 |
+
SizeDict,
|
| 31 |
+
get_image_size,
|
| 32 |
+
)
|
| 33 |
+
from ...modeling_flash_attention_utils import FlashAttentionKwargs
|
| 34 |
+
from ...modeling_outputs import BaseModelOutputWithPooling
|
| 35 |
+
from ...modeling_utils import PreTrainedModel
|
| 36 |
+
from ...processing_utils import ImagesKwargs, MultiModalData, ProcessingKwargs, ProcessorMixin, Unpack
|
| 37 |
+
from ...tokenization_python import PreTokenizedInput, TextInput
|
| 38 |
+
from ...utils import (
|
| 39 |
+
TensorType,
|
| 40 |
+
TransformersKwargs,
|
| 41 |
+
auto_docstring,
|
| 42 |
+
can_return_tuple,
|
| 43 |
+
logging,
|
| 44 |
+
)
|
| 45 |
+
from ..auto import CONFIG_MAPPING, AutoConfig, AutoTokenizer
|
| 46 |
+
from ..llama.configuration_llama import LlamaConfig
|
| 47 |
+
from ..llama.modeling_llama import (
|
| 48 |
+
LlamaAttention,
|
| 49 |
+
LlamaDecoderLayer,
|
| 50 |
+
LlamaForCausalLM,
|
| 51 |
+
LlamaMLP,
|
| 52 |
+
LlamaModel,
|
| 53 |
+
LlamaPreTrainedModel,
|
| 54 |
+
LlamaRMSNorm,
|
| 55 |
+
)
|
| 56 |
+
from ..llava.modeling_llava import (
|
| 57 |
+
LlavaCausalLMOutputWithPast,
|
| 58 |
+
LlavaForConditionalGeneration,
|
| 59 |
+
LlavaModel,
|
| 60 |
+
LlavaModelOutputWithPast,
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
logger = logging.get_logger(__name__)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def sequential_experts_gemm(token_states, expert_weights, tokens_per_expert):
|
| 68 |
+
"""
|
| 69 |
+
Compute the matrix multiplication (GEMM) for each expert sequentially. This approach is computationally inefficient, especially when dealing with a large number of experts.
|
| 70 |
+
|
| 71 |
+
Args:
|
| 72 |
+
token_states (torch.Tensor): Input tensor of shape (num_tokens, in_features).
|
| 73 |
+
expert_weights (torch.Tensor): Weight tensor of shape (num_experts, in_features, out_features).
|
| 74 |
+
tokens_per_expert (torch.Tensor): Number of tokens assigned to each expert.
|
| 75 |
+
|
| 76 |
+
Returns:
|
| 77 |
+
torch.Tensor: Output tensor of shape (num_tokens, out_features).
|
| 78 |
+
"""
|
| 79 |
+
num_tokens = token_states.shape[0]
|
| 80 |
+
out_features = expert_weights.shape[-1]
|
| 81 |
+
output = torch.zeros(num_tokens, out_features, dtype=token_states.dtype, device=token_states.device)
|
| 82 |
+
|
| 83 |
+
cumsum_num_tokens = torch.cumsum(tokens_per_expert, dim=0)
|
| 84 |
+
# Insert zero at the beginning for offset index's convenience
|
| 85 |
+
zero_tensor = torch.zeros(1, dtype=torch.long, device=cumsum_num_tokens.device)
|
| 86 |
+
cumsum_num_tokens = torch.cat((zero_tensor, cumsum_num_tokens))
|
| 87 |
+
|
| 88 |
+
for expert_num in range(expert_weights.shape[0]):
|
| 89 |
+
start = cumsum_num_tokens[expert_num]
|
| 90 |
+
end = cumsum_num_tokens[expert_num + 1]
|
| 91 |
+
tokens = token_states[start:end]
|
| 92 |
+
|
| 93 |
+
out = torch.matmul(tokens, expert_weights[expert_num])
|
| 94 |
+
output[start:end] = out
|
| 95 |
+
return output
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
@auto_docstring(checkpoint="rhymes-ai/Aria")
|
| 99 |
+
@strict
|
| 100 |
+
class AriaTextConfig(LlamaConfig):
|
| 101 |
+
r"""
|
| 102 |
+
moe_num_experts (`int`, *optional*, defaults to 8):
|
| 103 |
+
The number of experts in the MoE layer.
|
| 104 |
+
moe_topk (`int`, *optional*, defaults to 2):
|
| 105 |
+
The number of top experts to route to for each token.
|
| 106 |
+
moe_num_shared_experts (`int`, *optional*, defaults to 2):
|
| 107 |
+
The number of shared experts.
|
| 108 |
+
"""
|
| 109 |
+
|
| 110 |
+
model_type = "aria_text"
|
| 111 |
+
base_config_key = "text_config"
|
| 112 |
+
base_model_tp_plan = {
|
| 113 |
+
"layers.*.self_attn.q_proj": "colwise",
|
| 114 |
+
"layers.*.self_attn.k_proj": "colwise",
|
| 115 |
+
"layers.*.self_attn.v_proj": "colwise",
|
| 116 |
+
"layers.*.self_attn.o_proj": "rowwise",
|
| 117 |
+
"layers.*.mlp.shared_experts.gate_proj": "colwise",
|
| 118 |
+
"layers.*.mlp.shared_experts.up_proj": "colwise",
|
| 119 |
+
"layers.*.mlp.shared_experts.down_proj": "rowwise",
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
intermediate_size: int = 4096
|
| 123 |
+
moe_num_experts: int = 8
|
| 124 |
+
moe_topk: int = 2
|
| 125 |
+
moe_num_shared_experts: int = 2
|
| 126 |
+
pad_token_id: int | None = 2
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
@auto_docstring(checkpoint="rhymes-ai/Aria")
|
| 130 |
+
@strict
|
| 131 |
+
class AriaConfig(PreTrainedConfig):
|
| 132 |
+
r"""
|
| 133 |
+
projector_patch_to_query_dict (`dict`, *optional*):
|
| 134 |
+
Mapping of patch sizes to query dimensions.
|
| 135 |
+
"""
|
| 136 |
+
|
| 137 |
+
model_type = "aria"
|
| 138 |
+
attribute_map = {
|
| 139 |
+
"image_token_id": "image_token_index",
|
| 140 |
+
}
|
| 141 |
+
sub_configs = {"text_config": AriaTextConfig, "vision_config": AutoConfig}
|
| 142 |
+
|
| 143 |
+
vision_config: dict | PreTrainedConfig | None = None
|
| 144 |
+
text_config: dict | AriaTextConfig | None = None
|
| 145 |
+
vision_feature_layer: int | list[int] = -1
|
| 146 |
+
projector_patch_to_query_dict: dict | None = None
|
| 147 |
+
image_token_index: int = 9
|
| 148 |
+
initializer_range: float = 0.02
|
| 149 |
+
tie_word_embeddings: bool = False
|
| 150 |
+
|
| 151 |
+
def __post_init__(self, **kwargs):
|
| 152 |
+
# Convert the keys and values of projector_patch_to_query_dict to integers
|
| 153 |
+
# This ensures consistency even if they were provided as strings
|
| 154 |
+
if self.projector_patch_to_query_dict is None:
|
| 155 |
+
self.projector_patch_to_query_dict = {
|
| 156 |
+
1225: 128,
|
| 157 |
+
4900: 256,
|
| 158 |
+
}
|
| 159 |
+
self.projector_patch_to_query_dict = {int(k): int(v) for k, v in self.projector_patch_to_query_dict.items()}
|
| 160 |
+
self.max_value_projector_patch_to_query_dict = max(self.projector_patch_to_query_dict.values())
|
| 161 |
+
|
| 162 |
+
if isinstance(self.vision_config, dict):
|
| 163 |
+
self.vision_config["model_type"] = "idefics3_vision"
|
| 164 |
+
self.vision_config = CONFIG_MAPPING[self.vision_config["model_type"]](**self.vision_config)
|
| 165 |
+
elif self.vision_config is None:
|
| 166 |
+
self.vision_config = CONFIG_MAPPING["idefics3_vision"]()
|
| 167 |
+
|
| 168 |
+
if isinstance(self.text_config, dict) and "model_type" in self.text_config:
|
| 169 |
+
self.text_config = AriaTextConfig(**self.text_config)
|
| 170 |
+
elif self.text_config is None:
|
| 171 |
+
self.text_config = AriaTextConfig()
|
| 172 |
+
|
| 173 |
+
super().__post_init__(**kwargs)
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
class AriaTextRMSNorm(LlamaRMSNorm):
|
| 177 |
+
pass
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
class AriaProjectorMLP(nn.Module):
|
| 181 |
+
"""
|
| 182 |
+
Feed-Forward Network module for the Aria Projector.
|
| 183 |
+
|
| 184 |
+
Args:
|
| 185 |
+
in_features (`int`):
|
| 186 |
+
Input embedding dimension.
|
| 187 |
+
hidden_features (`int`):
|
| 188 |
+
Hidden dimension of the feed-forward network.
|
| 189 |
+
output_dim (`int`):
|
| 190 |
+
Output dimension.
|
| 191 |
+
"""
|
| 192 |
+
|
| 193 |
+
def __init__(self, in_features, hidden_features, output_dim):
|
| 194 |
+
super().__init__()
|
| 195 |
+
self.linear_in = nn.Linear(in_features, hidden_features, bias=False)
|
| 196 |
+
self.linear_out = nn.Linear(hidden_features, output_dim, bias=False)
|
| 197 |
+
self.act = ACT2FN["gelu_new"]
|
| 198 |
+
|
| 199 |
+
def forward(self, hidden_states):
|
| 200 |
+
hidden_states = self.act(self.linear_in(hidden_states))
|
| 201 |
+
hidden_states = self.linear_out(hidden_states)
|
| 202 |
+
return hidden_states
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
class AriaCrossAttention(nn.Module):
|
| 206 |
+
"""
|
| 207 |
+
Aria Cross-Attention module.
|
| 208 |
+
|
| 209 |
+
Args:
|
| 210 |
+
config (`AriaConfig`):
|
| 211 |
+
The configuration to use.
|
| 212 |
+
"""
|
| 213 |
+
|
| 214 |
+
def __init__(self, config: AriaConfig, dropout_rate: float = 0):
|
| 215 |
+
super().__init__()
|
| 216 |
+
hidden_size = config.vision_config.hidden_size
|
| 217 |
+
num_heads = config.vision_config.num_attention_heads
|
| 218 |
+
self.num_heads = num_heads
|
| 219 |
+
self.q_proj = nn.Linear(hidden_size, hidden_size, bias=False)
|
| 220 |
+
self.k_proj = nn.Linear(hidden_size, hidden_size, bias=False)
|
| 221 |
+
self.v_proj = nn.Linear(hidden_size, hidden_size, bias=False)
|
| 222 |
+
|
| 223 |
+
# Original code here: https://github.com/rhymes-ai/Aria/blob/719ff4e52b727443cba3793b0e27fe64e0244fe1/aria/model/projector.py#L48
|
| 224 |
+
self.multihead_attn = nn.MultiheadAttention(hidden_size, num_heads, batch_first=True)
|
| 225 |
+
self.linear = nn.Linear(hidden_size, hidden_size)
|
| 226 |
+
self.dropout = nn.Dropout(dropout_rate)
|
| 227 |
+
|
| 228 |
+
self.layer_norm = nn.LayerNorm(hidden_size)
|
| 229 |
+
self.layer_norm_kv = nn.LayerNorm(hidden_size)
|
| 230 |
+
|
| 231 |
+
def forward(self, key_value_states, hidden_states, attn_mask=None):
|
| 232 |
+
"""
|
| 233 |
+
Forward pass of the AriaCrossAttention module.
|
| 234 |
+
|
| 235 |
+
Args:
|
| 236 |
+
key_value_states (`torch.Tensor`):
|
| 237 |
+
Input tensor for key and value.
|
| 238 |
+
hidden_states (`torch.Tensor`):
|
| 239 |
+
Input tensor for query.
|
| 240 |
+
attn_mask (`torch.Tensor`, *optional*, defaults to None):
|
| 241 |
+
Attention mask.
|
| 242 |
+
|
| 243 |
+
Returns:
|
| 244 |
+
torch.Tensor:
|
| 245 |
+
Output tensor after cross-attention.
|
| 246 |
+
"""
|
| 247 |
+
query = self.q_proj(self.layer_norm(hidden_states))
|
| 248 |
+
|
| 249 |
+
key_value_states = self.layer_norm_kv(key_value_states)
|
| 250 |
+
key = self.k_proj(key_value_states)
|
| 251 |
+
value = self.v_proj(key_value_states)
|
| 252 |
+
|
| 253 |
+
attn_output, _ = self.multihead_attn(query, key, value, attn_mask=attn_mask)
|
| 254 |
+
|
| 255 |
+
attn_output = self.dropout(self.linear(attn_output))
|
| 256 |
+
|
| 257 |
+
return attn_output
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
class AriaProjector(nn.Module):
|
| 261 |
+
"""
|
| 262 |
+
Aria Projector module.
|
| 263 |
+
|
| 264 |
+
This module projects vision features into the language model's embedding space, enabling interaction between vision and language components.
|
| 265 |
+
|
| 266 |
+
Args:
|
| 267 |
+
config (`AriaConfig`):
|
| 268 |
+
Configuration object for the model.
|
| 269 |
+
"""
|
| 270 |
+
|
| 271 |
+
def __init__(
|
| 272 |
+
self,
|
| 273 |
+
config: AriaConfig,
|
| 274 |
+
):
|
| 275 |
+
super().__init__()
|
| 276 |
+
|
| 277 |
+
self.patch_to_query_dict = config.projector_patch_to_query_dict
|
| 278 |
+
self.in_features = config.vision_config.hidden_size
|
| 279 |
+
self.num_heads = config.vision_config.num_attention_heads
|
| 280 |
+
self.kv_dim = config.vision_config.hidden_size
|
| 281 |
+
self.hidden_features = config.text_config.hidden_size
|
| 282 |
+
self.output_dim = config.text_config.hidden_size
|
| 283 |
+
|
| 284 |
+
self.query = nn.Parameter(torch.zeros(config.max_value_projector_patch_to_query_dict, self.in_features))
|
| 285 |
+
|
| 286 |
+
self.cross_attn = AriaCrossAttention(config)
|
| 287 |
+
|
| 288 |
+
self.layer_norm = nn.LayerNorm(self.in_features)
|
| 289 |
+
self.feed_forward = AriaProjectorMLP(self.in_features, self.hidden_features, self.output_dim)
|
| 290 |
+
|
| 291 |
+
def forward(self, key_value_states: torch.Tensor, attn_mask: torch.Tensor | None = None):
|
| 292 |
+
"""
|
| 293 |
+
Forward pass of the Projector module.
|
| 294 |
+
|
| 295 |
+
Args:
|
| 296 |
+
key_value_states (`torch.Tensor`):
|
| 297 |
+
Input tensor of shape (batch_size, num_patches, kv_dim).
|
| 298 |
+
attn_mask (`torch.Tensor`, *optional*, default is None):
|
| 299 |
+
Attention mask.
|
| 300 |
+
|
| 301 |
+
Returns:
|
| 302 |
+
`torch.Tensor`: Output tensor of shape (batch_size, query_number, output_dim).
|
| 303 |
+
"""
|
| 304 |
+
batch_size, num_patches = key_value_states.shape[0], key_value_states.shape[1]
|
| 305 |
+
|
| 306 |
+
if num_patches not in self.patch_to_query_dict:
|
| 307 |
+
raise KeyError(
|
| 308 |
+
f"Number of patches {num_patches} not found in patch_to_query_dict amongst possible values {self.patch_to_query_dict.keys()}."
|
| 309 |
+
)
|
| 310 |
+
query_num = self.patch_to_query_dict[num_patches]
|
| 311 |
+
|
| 312 |
+
queries = self.query[:query_num].unsqueeze(0).repeat(batch_size, 1, 1)
|
| 313 |
+
|
| 314 |
+
if attn_mask is not None:
|
| 315 |
+
attn_mask = attn_mask.repeat_interleave(self.num_heads, 0)
|
| 316 |
+
attn_mask = attn_mask.unsqueeze(1).expand(-1, queries.size(1), -1)
|
| 317 |
+
|
| 318 |
+
attention_out = self.cross_attn(key_value_states, queries, attn_mask=attn_mask)
|
| 319 |
+
|
| 320 |
+
out = self.feed_forward(self.layer_norm(attention_out))
|
| 321 |
+
|
| 322 |
+
return out
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
class AriaImageProcessorKwargs(ImagesKwargs, total=False):
|
| 326 |
+
r"""
|
| 327 |
+
max_image_size (`int`, *optional*, defaults to `self.max_image_size`):
|
| 328 |
+
Maximum image size. Must be either 490 or 980.
|
| 329 |
+
min_image_size (`int`, *optional*, defaults to `self.min_image_size`):
|
| 330 |
+
Minimum image size. Images smaller than this in any dimension will be scaled up.
|
| 331 |
+
split_resolutions (`list[list[int]]`, *optional*, defaults to `self.split_resolutions`):
|
| 332 |
+
A list of possible resolutions as (height, width) pairs for splitting high-resolution images into patches.
|
| 333 |
+
split_image (`bool`, *optional*, defaults to `self.split_image`):
|
| 334 |
+
Whether to split the image into patches using the best matching resolution from `split_resolutions`.
|
| 335 |
+
"""
|
| 336 |
+
|
| 337 |
+
max_image_size: int
|
| 338 |
+
min_image_size: int
|
| 339 |
+
split_resolutions: list[list[int]]
|
| 340 |
+
split_image: bool
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
@auto_docstring
|
| 344 |
+
class AriaImageProcessor(TorchvisionBackend):
|
| 345 |
+
model_input_names = ["pixel_values", "pixel_mask", "num_crops"]
|
| 346 |
+
valid_kwargs = AriaImageProcessorKwargs
|
| 347 |
+
|
| 348 |
+
resample = PILImageResampling.BICUBIC
|
| 349 |
+
image_mean = [0.5, 0.5, 0.5]
|
| 350 |
+
image_std = [0.5, 0.5, 0.5]
|
| 351 |
+
max_image_size = 980
|
| 352 |
+
min_image_size = 336
|
| 353 |
+
split_image = False
|
| 354 |
+
split_resolutions = None
|
| 355 |
+
do_convert_rgb = True
|
| 356 |
+
do_rescale = True
|
| 357 |
+
do_normalize = True
|
| 358 |
+
|
| 359 |
+
def __init__(self, **kwargs: Unpack[AriaImageProcessorKwargs]):
|
| 360 |
+
if kwargs.get("split_resolutions") is None:
|
| 361 |
+
default_resolutions = [(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (2, 4), (2, 3), (2, 2), (2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (5, 1), (6, 1), (7, 1), (8, 1)] # fmt: skip
|
| 362 |
+
kwargs["split_resolutions"] = [[el[0] * 490, el[1] * 490] for el in default_resolutions]
|
| 363 |
+
super().__init__(**kwargs)
|
| 364 |
+
|
| 365 |
+
def _get_padding_size(self, original_resolution: tuple, target_resolution: tuple) -> list[int]:
|
| 366 |
+
"""Get padding size for patching, returns [left, top, right, bottom] for tvF.pad."""
|
| 367 |
+
original_height, original_width = original_resolution
|
| 368 |
+
target_height, target_width = target_resolution
|
| 369 |
+
paste_x, r_x = divmod(target_width - original_width, 2)
|
| 370 |
+
paste_y, r_y = divmod(target_height - original_height, 2)
|
| 371 |
+
return [paste_x, paste_y, paste_x + r_x, paste_y + r_y]
|
| 372 |
+
|
| 373 |
+
def _resize_for_patching(
|
| 374 |
+
self,
|
| 375 |
+
image: "torch.Tensor",
|
| 376 |
+
target_resolution: tuple,
|
| 377 |
+
resample: "PILImageResampling | tvF.InterpolationMode | int | None",
|
| 378 |
+
) -> "torch.Tensor":
|
| 379 |
+
"""Resize an image to a target resolution while maintaining aspect ratio."""
|
| 380 |
+
new_height, new_width = get_patch_output_size(
|
| 381 |
+
image, target_resolution, input_data_format=ChannelDimension.FIRST
|
| 382 |
+
)
|
| 383 |
+
return self.resize(image, SizeDict(height=new_height, width=new_width), resample)
|
| 384 |
+
|
| 385 |
+
def _pad_for_patching(
|
| 386 |
+
self,
|
| 387 |
+
image: "torch.Tensor",
|
| 388 |
+
target_resolution: tuple,
|
| 389 |
+
) -> "torch.Tensor":
|
| 390 |
+
"""Pad an image to a target resolution while maintaining aspect ratio."""
|
| 391 |
+
new_resolution = get_patch_output_size(image, target_resolution, input_data_format=ChannelDimension.FIRST)
|
| 392 |
+
padding = self._get_padding_size(new_resolution, target_resolution)
|
| 393 |
+
return tvF.pad(image, padding=padding)
|
| 394 |
+
|
| 395 |
+
def get_image_patches(
|
| 396 |
+
self,
|
| 397 |
+
image: "torch.Tensor",
|
| 398 |
+
grid_pinpoints: list[list[int]],
|
| 399 |
+
patch_size: int,
|
| 400 |
+
resample: "PILImageResampling | tvF.InterpolationMode | int | None",
|
| 401 |
+
) -> list["torch.Tensor"]:
|
| 402 |
+
"""
|
| 403 |
+
Process an image with variable resolutions by dividing it into patches.
|
| 404 |
+
|
| 405 |
+
Args:
|
| 406 |
+
image (`torch.Tensor`):
|
| 407 |
+
The input image to be processed (channels-first format).
|
| 408 |
+
grid_pinpoints (`list[list[int]]`):
|
| 409 |
+
A list of possible resolutions as (height, width) pairs.
|
| 410 |
+
patch_size (`int`):
|
| 411 |
+
Size of each square patch to divide the image into.
|
| 412 |
+
resample (`PILImageResampling | tvF.InterpolationMode | int | None`):
|
| 413 |
+
Resampling filter to use when resizing.
|
| 414 |
+
|
| 415 |
+
Returns:
|
| 416 |
+
`list[torch.Tensor]`: A list of image patches in channels-first format.
|
| 417 |
+
"""
|
| 418 |
+
if not isinstance(grid_pinpoints, list):
|
| 419 |
+
raise TypeError("grid_pinpoints must be a list of possible resolutions.")
|
| 420 |
+
|
| 421 |
+
image_size = get_image_size(image, channel_dim=ChannelDimension.FIRST)
|
| 422 |
+
best_resolution = select_best_resolution(image_size, grid_pinpoints)
|
| 423 |
+
resized_image = self._resize_for_patching(image, best_resolution, resample)
|
| 424 |
+
padded_image = self._pad_for_patching(resized_image, best_resolution)
|
| 425 |
+
patches = divide_to_patches(padded_image, patch_size=patch_size)
|
| 426 |
+
return patches
|
| 427 |
+
|
| 428 |
+
def _preprocess(
|
| 429 |
+
self,
|
| 430 |
+
images: list["torch.Tensor"],
|
| 431 |
+
do_rescale: bool,
|
| 432 |
+
rescale_factor: float,
|
| 433 |
+
do_normalize: bool,
|
| 434 |
+
image_mean: float | list[float] | None,
|
| 435 |
+
image_std: float | list[float] | None,
|
| 436 |
+
disable_grouping: bool | None,
|
| 437 |
+
return_tensors: str | TensorType | None,
|
| 438 |
+
max_image_size: int = 980,
|
| 439 |
+
min_image_size: int = 336,
|
| 440 |
+
split_resolutions: list[list[int]] | None = None,
|
| 441 |
+
split_image: bool = False,
|
| 442 |
+
resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None,
|
| 443 |
+
**kwargs,
|
| 444 |
+
) -> BatchFeature:
|
| 445 |
+
if max_image_size not in [490, 980]:
|
| 446 |
+
raise ValueError("max_image_size must be either 490 or 980")
|
| 447 |
+
|
| 448 |
+
pixel_masks = []
|
| 449 |
+
processed_crops = []
|
| 450 |
+
num_crops = None
|
| 451 |
+
|
| 452 |
+
for image in images:
|
| 453 |
+
if split_image:
|
| 454 |
+
crop_images = self.get_image_patches(image, split_resolutions, max_image_size, resample)
|
| 455 |
+
else:
|
| 456 |
+
crop_images = [image]
|
| 457 |
+
|
| 458 |
+
if num_crops is None or len(crop_images) > num_crops:
|
| 459 |
+
num_crops = len(crop_images)
|
| 460 |
+
|
| 461 |
+
for crop_image in crop_images:
|
| 462 |
+
h, w = crop_image.shape[-2], crop_image.shape[-1]
|
| 463 |
+
scale = max_image_size / max(h, w)
|
| 464 |
+
if w >= h:
|
| 465 |
+
new_h = max(int(h * scale), min_image_size)
|
| 466 |
+
new_w = max_image_size
|
| 467 |
+
else:
|
| 468 |
+
new_h = max_image_size
|
| 469 |
+
new_w = max(int(w * scale), min_image_size)
|
| 470 |
+
|
| 471 |
+
crop_image = self.resize(crop_image, SizeDict(height=new_h, width=new_w), resample)
|
| 472 |
+
|
| 473 |
+
padding_bottom = max_image_size - new_h
|
| 474 |
+
padding_right = max_image_size - new_w
|
| 475 |
+
crop_image = tvF.pad(crop_image, [0, 0, padding_right, padding_bottom])
|
| 476 |
+
|
| 477 |
+
pixel_mask = torch.zeros((max_image_size, max_image_size), dtype=torch.bool)
|
| 478 |
+
pixel_mask[:new_h, :new_w] = True
|
| 479 |
+
pixel_masks.append(pixel_mask)
|
| 480 |
+
processed_crops.append(crop_image)
|
| 481 |
+
|
| 482 |
+
stacked_images = torch.stack(processed_crops, dim=0)
|
| 483 |
+
stacked_images = self.rescale_and_normalize(
|
| 484 |
+
stacked_images, do_rescale, rescale_factor, do_normalize, image_mean, image_std
|
| 485 |
+
)
|
| 486 |
+
stacked_masks = torch.stack(pixel_masks, dim=0)
|
| 487 |
+
|
| 488 |
+
return BatchFeature(
|
| 489 |
+
data={
|
| 490 |
+
"pixel_values": stacked_images,
|
| 491 |
+
"pixel_mask": stacked_masks,
|
| 492 |
+
"num_crops": num_crops,
|
| 493 |
+
},
|
| 494 |
+
tensor_type=return_tensors,
|
| 495 |
+
)
|
| 496 |
+
|
| 497 |
+
def get_number_of_image_patches(self, height: int, width: int, images_kwargs=None):
|
| 498 |
+
"""
|
| 499 |
+
A utility that returns number of image patches for a given image size.
|
| 500 |
+
|
| 501 |
+
Args:
|
| 502 |
+
height (`int`):
|
| 503 |
+
Height of the input image.
|
| 504 |
+
width (`int`):
|
| 505 |
+
Width of the input image.
|
| 506 |
+
images_kwargs (`dict`, *optional*):
|
| 507 |
+
Any kwargs to override defaults of the image processor.
|
| 508 |
+
|
| 509 |
+
Returns:
|
| 510 |
+
`int`: Number of patches per image.
|
| 511 |
+
"""
|
| 512 |
+
split_image = images_kwargs.get("split_image", self.split_image)
|
| 513 |
+
max_image_size = images_kwargs.get("max_image_size", self.max_image_size)
|
| 514 |
+
|
| 515 |
+
resized_height, resized_width = select_best_resolution((height, width), self.split_resolutions)
|
| 516 |
+
num_patches = 1 if not split_image else resized_height // max_image_size * resized_width // max_image_size
|
| 517 |
+
return num_patches
|
| 518 |
+
|
| 519 |
+
|
| 520 |
+
class AriaImagesKwargs(ImagesKwargs, total=False):
|
| 521 |
+
"""
|
| 522 |
+
split_image (`bool`, *optional*, defaults to `False`):
|
| 523 |
+
Whether to split large images into multiple crops. When enabled, images exceeding the maximum size are
|
| 524 |
+
divided into overlapping crops that are processed separately and then combined. This allows processing
|
| 525 |
+
of very high-resolution images that exceed the model's input size limits.
|
| 526 |
+
max_image_size (`int`, *optional*, defaults to `980`):
|
| 527 |
+
Maximum image size (in pixels) for a single image crop. Images larger than this will be split into
|
| 528 |
+
multiple crops when `split_image=True`, or resized if splitting is disabled. This parameter controls
|
| 529 |
+
the maximum resolution of individual image patches processed by the model.
|
| 530 |
+
min_image_size (`int`, *optional*):
|
| 531 |
+
Minimum image size (in pixels) for a single image crop. Images smaller than this will be upscaled to
|
| 532 |
+
meet the minimum requirement. If not specified, images are processed at their original size (subject
|
| 533 |
+
to the maximum size constraint).
|
| 534 |
+
"""
|
| 535 |
+
|
| 536 |
+
split_image: bool
|
| 537 |
+
max_image_size: int
|
| 538 |
+
min_image_size: int
|
| 539 |
+
|
| 540 |
+
|
| 541 |
+
class AriaProcessorKwargs(ProcessingKwargs, total=False):
|
| 542 |
+
images_kwargs: AriaImagesKwargs
|
| 543 |
+
|
| 544 |
+
_defaults = {
|
| 545 |
+
"text_kwargs": {
|
| 546 |
+
"padding": False,
|
| 547 |
+
"return_mm_token_type_ids": False,
|
| 548 |
+
},
|
| 549 |
+
"images_kwargs": {
|
| 550 |
+
"max_image_size": 980,
|
| 551 |
+
"split_image": False,
|
| 552 |
+
},
|
| 553 |
+
"return_tensors": TensorType.PYTORCH,
|
| 554 |
+
}
|
| 555 |
+
|
| 556 |
+
|
| 557 |
+
@auto_docstring
|
| 558 |
+
class AriaProcessor(ProcessorMixin):
|
| 559 |
+
def __init__(
|
| 560 |
+
self,
|
| 561 |
+
image_processor=None,
|
| 562 |
+
tokenizer: AutoTokenizer | str = None,
|
| 563 |
+
chat_template: str | None = None,
|
| 564 |
+
size_conversion: dict[float | int, int] | None = None,
|
| 565 |
+
):
|
| 566 |
+
r"""
|
| 567 |
+
size_conversion (`Dict`, *optional*):
|
| 568 |
+
A dictionary indicating size conversions for images.
|
| 569 |
+
"""
|
| 570 |
+
if size_conversion is None:
|
| 571 |
+
size_conversion = {490: 128, 980: 256}
|
| 572 |
+
self.size_conversion = {int(k): v for k, v in size_conversion.items()}
|
| 573 |
+
|
| 574 |
+
self.image_token = tokenizer.image_token
|
| 575 |
+
self.image_token_id = tokenizer.image_token_id
|
| 576 |
+
if tokenizer is not None and tokenizer.pad_token is None:
|
| 577 |
+
tokenizer.pad_token = tokenizer.unk_token
|
| 578 |
+
|
| 579 |
+
super().__init__(image_processor, tokenizer, chat_template=chat_template)
|
| 580 |
+
|
| 581 |
+
@auto_docstring
|
| 582 |
+
def __call__(
|
| 583 |
+
self,
|
| 584 |
+
text: TextInput | PreTokenizedInput | list[TextInput] | list[PreTokenizedInput],
|
| 585 |
+
images: ImageInput | None = None,
|
| 586 |
+
**kwargs: Unpack[AriaProcessorKwargs],
|
| 587 |
+
) -> BatchFeature:
|
| 588 |
+
r"""
|
| 589 |
+
Returns:
|
| 590 |
+
[`BatchFeature`]: A [`BatchFeature`] with the following fields:
|
| 591 |
+
- **input_ids** -- List of token ids to be fed to a model. Returned when `text` is not `None`.
|
| 592 |
+
- **attention_mask** -- List of indices specifying which tokens should be attended to by the model (when
|
| 593 |
+
`return_attention_mask=True` or if *"attention_mask"* is in `self.model_input_names` and if `text` is not
|
| 594 |
+
`None`).
|
| 595 |
+
- **pixel_values** -- Pixel values to be fed to a model. Returned when `images` is not `None`.
|
| 596 |
+
- **pixel_mask** -- Pixel mask to be fed to a model. Returned when `images` is not `None`.
|
| 597 |
+
"""
|
| 598 |
+
output_kwargs = self._merge_kwargs(
|
| 599 |
+
AriaProcessorKwargs,
|
| 600 |
+
tokenizer_init_kwargs=self.tokenizer.init_kwargs,
|
| 601 |
+
**kwargs,
|
| 602 |
+
)
|
| 603 |
+
|
| 604 |
+
if isinstance(text, str):
|
| 605 |
+
text = [text]
|
| 606 |
+
elif not isinstance(text, list) and not isinstance(text[0], str):
|
| 607 |
+
raise TypeError("Invalid input text. Please provide a string, or a list of strings")
|
| 608 |
+
|
| 609 |
+
if images is not None:
|
| 610 |
+
image_inputs = self.image_processor(images, **output_kwargs["images_kwargs"])
|
| 611 |
+
# expand the image_token according to the num_crops and tokens per image
|
| 612 |
+
tokens_per_image = self.size_conversion[image_inputs.pixel_values.shape[2]]
|
| 613 |
+
prompt_strings = []
|
| 614 |
+
num_crops = image_inputs.pop("num_crops") * tokens_per_image
|
| 615 |
+
for sample in text:
|
| 616 |
+
sample = sample.replace(self.tokenizer.image_token, self.tokenizer.image_token * num_crops)
|
| 617 |
+
prompt_strings.append(sample)
|
| 618 |
+
|
| 619 |
+
else:
|
| 620 |
+
image_inputs = {}
|
| 621 |
+
prompt_strings = text
|
| 622 |
+
|
| 623 |
+
return_tensors = output_kwargs["text_kwargs"].pop("return_tensors", None)
|
| 624 |
+
return_mm_token_type_ids = output_kwargs["text_kwargs"].pop("return_mm_token_type_ids", False)
|
| 625 |
+
text_inputs = self.tokenizer(prompt_strings, **output_kwargs["text_kwargs"], return_tensors=None)
|
| 626 |
+
self._check_special_mm_tokens(prompt_strings, text_inputs, modalities=["image"])
|
| 627 |
+
|
| 628 |
+
if return_mm_token_type_ids:
|
| 629 |
+
text_inputs["mm_token_type_ids"] = self.create_mm_token_type_ids(text_inputs["input_ids"])
|
| 630 |
+
return BatchFeature(data={**text_inputs, **image_inputs}, tensor_type=return_tensors)
|
| 631 |
+
|
| 632 |
+
def _get_num_multimodal_tokens(self, image_sizes=None, **kwargs):
|
| 633 |
+
"""
|
| 634 |
+
Computes the number of placeholder tokens needed for multimodal inputs with the given sizes.
|
| 635 |
+
Args:
|
| 636 |
+
image_sizes (`list[list[int]]`, *optional*):
|
| 637 |
+
The input sizes formatted as (height, width) per each image.
|
| 638 |
+
Returns:
|
| 639 |
+
`MultiModalData`: A `MultiModalData` object holding number of tokens per each of the provided
|
| 640 |
+
input modalities, along with other useful data.
|
| 641 |
+
"""
|
| 642 |
+
|
| 643 |
+
vision_data = {}
|
| 644 |
+
if image_sizes is not None:
|
| 645 |
+
images_kwargs = AriaProcessorKwargs._defaults.get("images_kwargs", {})
|
| 646 |
+
images_kwargs.update(kwargs)
|
| 647 |
+
|
| 648 |
+
max_size = images_kwargs.get("max_image_size", None) or self.image_processor.max_image_size
|
| 649 |
+
num_image_patches = [
|
| 650 |
+
self.image_processor.get_number_of_image_patches(*image_size, images_kwargs)
|
| 651 |
+
for image_size in image_sizes
|
| 652 |
+
]
|
| 653 |
+
num_image_tokens = [self.size_conversion[max_size] * num_patches for num_patches in num_image_patches]
|
| 654 |
+
vision_data.update({"num_image_tokens": num_image_tokens, "num_image_patches": num_image_patches})
|
| 655 |
+
|
| 656 |
+
return MultiModalData(**vision_data)
|
| 657 |
+
|
| 658 |
+
@property
|
| 659 |
+
def model_input_names(self):
|
| 660 |
+
tokenizer_input_names = self.tokenizer.model_input_names
|
| 661 |
+
image_processor_input_names = self.image_processor.model_input_names
|
| 662 |
+
|
| 663 |
+
# Remove `num_crops`, it is popped and used only when processing. Make a copy of list when removing
|
| 664 |
+
# otherwise `self.image_processor.model_input_names` is also modified
|
| 665 |
+
image_processor_input_names = [name for name in image_processor_input_names if name != "num_crops"]
|
| 666 |
+
return list(dict.fromkeys(tokenizer_input_names + image_processor_input_names))
|
| 667 |
+
|
| 668 |
+
|
| 669 |
+
class AriaSharedExpertsMLP(LlamaMLP):
|
| 670 |
+
"""
|
| 671 |
+
Shared Expert MLP for shared experts.
|
| 672 |
+
|
| 673 |
+
Unlike routed experts, shared experts process all tokens without routing.
|
| 674 |
+
This class reconfigures the intermediate size in comparison to the LlamaMLP.
|
| 675 |
+
|
| 676 |
+
Args:
|
| 677 |
+
config (`AriaTextConfig`): Configuration object for the Aria language model.
|
| 678 |
+
"""
|
| 679 |
+
|
| 680 |
+
def __init__(self, config: AriaTextConfig):
|
| 681 |
+
super().__init__(config)
|
| 682 |
+
self.intermediate_size = config.intermediate_size * config.moe_num_shared_experts
|
| 683 |
+
|
| 684 |
+
|
| 685 |
+
class AriaGroupedExpertsGemm(nn.Module):
|
| 686 |
+
"""
|
| 687 |
+
Grouped GEMM (General Matrix Multiplication) module for efficient expert computation.
|
| 688 |
+
This module utilizes the grouped_gemm library (https://github.com/fanshiqing/grouped_gemm)
|
| 689 |
+
for optimized performance. If the grouped_gemm library is not installed, it gracefully
|
| 690 |
+
falls back to a sequential GEMM implementation, which may be slower but ensures
|
| 691 |
+
functionality.
|
| 692 |
+
|
| 693 |
+
Args:
|
| 694 |
+
in_features (`int`):
|
| 695 |
+
Number of input features.
|
| 696 |
+
out_features (`int`):
|
| 697 |
+
Number of output features.
|
| 698 |
+
groups (`int`):
|
| 699 |
+
Number of expert groups.
|
| 700 |
+
"""
|
| 701 |
+
|
| 702 |
+
def __init__(self, in_features, out_features, groups):
|
| 703 |
+
super().__init__()
|
| 704 |
+
self.in_features = in_features
|
| 705 |
+
self.out_features = out_features
|
| 706 |
+
self.groups = groups
|
| 707 |
+
self.weight = nn.Parameter(torch.empty(groups, in_features, out_features))
|
| 708 |
+
|
| 709 |
+
def forward(self, input, tokens_per_expert):
|
| 710 |
+
"""
|
| 711 |
+
Perform grouped matrix multiplication.
|
| 712 |
+
|
| 713 |
+
Args:
|
| 714 |
+
input (`torch.Tensor`):
|
| 715 |
+
Input tensor of shape (num_tokens, in_features).
|
| 716 |
+
tokens_per_expert (`torch.Tensor`):
|
| 717 |
+
Number of tokens assigned to each expert.
|
| 718 |
+
|
| 719 |
+
Returns:
|
| 720 |
+
torch.Tensor: Output tensor of shape (num_tokens, out_features).
|
| 721 |
+
"""
|
| 722 |
+
return sequential_experts_gemm(
|
| 723 |
+
input,
|
| 724 |
+
self.weight,
|
| 725 |
+
tokens_per_expert.cpu(),
|
| 726 |
+
)
|
| 727 |
+
|
| 728 |
+
|
| 729 |
+
class AriaExperts(nn.Module):
|
| 730 |
+
def __init__(self, config: AriaTextConfig) -> None:
|
| 731 |
+
super().__init__()
|
| 732 |
+
self.config = config
|
| 733 |
+
self.fc1 = AriaGroupedExpertsGemm(config.hidden_size, config.intermediate_size * 2, config.moe_num_experts)
|
| 734 |
+
self.fc2 = AriaGroupedExpertsGemm(config.intermediate_size, config.hidden_size, config.moe_num_experts)
|
| 735 |
+
|
| 736 |
+
def route_tokens_to_experts(self, router_logits):
|
| 737 |
+
top_logits, top_indices = torch.topk(router_logits, k=self.config.moe_topk, dim=1)
|
| 738 |
+
scores = nn.functional.softmax(top_logits, dim=-1)
|
| 739 |
+
return top_indices, scores
|
| 740 |
+
|
| 741 |
+
def forward(self, hidden_states, router_logits) -> torch.Tensor:
|
| 742 |
+
top_k_index, top_k_weights = self.route_tokens_to_experts(router_logits)
|
| 743 |
+
original_dtype = top_k_index.dtype
|
| 744 |
+
tokens_per_expert = torch.histc(
|
| 745 |
+
top_k_index.flatten().to(torch.float32),
|
| 746 |
+
bins=self.config.moe_num_experts,
|
| 747 |
+
min=0,
|
| 748 |
+
max=self.config.moe_num_experts - 1,
|
| 749 |
+
).to(original_dtype)
|
| 750 |
+
indices = top_k_index
|
| 751 |
+
|
| 752 |
+
flatten_indices = indices.view(-1)
|
| 753 |
+
sorted_indices = torch.argsort(flatten_indices)
|
| 754 |
+
permuted_tokens = hidden_states.index_select(0, sorted_indices // self.config.moe_topk)
|
| 755 |
+
|
| 756 |
+
fc1_output = self.fc1(permuted_tokens, tokens_per_expert)
|
| 757 |
+
projection, gate = torch.chunk(fc1_output, 2, dim=-1)
|
| 758 |
+
fc1_output = nn.functional.silu(projection) * gate
|
| 759 |
+
expert_output = self.fc2(fc1_output, tokens_per_expert)
|
| 760 |
+
|
| 761 |
+
unpermuted_tokens = torch.zeros(
|
| 762 |
+
(top_k_weights.shape[0] * self.config.moe_topk, expert_output.size(1)),
|
| 763 |
+
dtype=expert_output.dtype,
|
| 764 |
+
device=expert_output.device,
|
| 765 |
+
)
|
| 766 |
+
unpermuted_tokens.index_copy_(0, sorted_indices, expert_output)
|
| 767 |
+
unpermuted_tokens = unpermuted_tokens.view(-1, self.config.moe_topk, expert_output.size(1))
|
| 768 |
+
|
| 769 |
+
output = (unpermuted_tokens * top_k_weights.unsqueeze(-1)).sum(dim=1)
|
| 770 |
+
return output
|
| 771 |
+
|
| 772 |
+
|
| 773 |
+
class AriaTextMoELayer(nn.Module):
|
| 774 |
+
def __init__(self, config: AriaTextConfig):
|
| 775 |
+
super().__init__()
|
| 776 |
+
self.router = nn.Linear(config.hidden_size, config.moe_num_experts, bias=False)
|
| 777 |
+
self.experts = AriaExperts(config)
|
| 778 |
+
self.shared_experts = AriaSharedExpertsMLP(config)
|
| 779 |
+
self.config = config
|
| 780 |
+
|
| 781 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 782 |
+
original_shape = hidden_states.shape
|
| 783 |
+
hidden_states = hidden_states.view(-1, hidden_states.size(-1))
|
| 784 |
+
router_logits = self.router(hidden_states)
|
| 785 |
+
expert_output = self.experts(hidden_states, router_logits).view(original_shape)
|
| 786 |
+
shared_expert_output = self.shared_experts(hidden_states.view(original_shape))
|
| 787 |
+
return expert_output + shared_expert_output
|
| 788 |
+
|
| 789 |
+
|
| 790 |
+
class AriaTextAttention(LlamaAttention):
|
| 791 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 792 |
+
|
| 793 |
+
|
| 794 |
+
class AriaTextDecoderLayer(LlamaDecoderLayer):
|
| 795 |
+
"""
|
| 796 |
+
Aria Text Decoder Layer.
|
| 797 |
+
|
| 798 |
+
This class defines a single decoder layer in the language model, incorporating self-attention and Mixture of Experts (MoE) feed-forward network.
|
| 799 |
+
|
| 800 |
+
Args:
|
| 801 |
+
config (`AriaTextConfig`):
|
| 802 |
+
Configuration object for the text component of the model.
|
| 803 |
+
layer_idx (`int`):
|
| 804 |
+
Index of the layer.
|
| 805 |
+
"""
|
| 806 |
+
|
| 807 |
+
def __init__(self, config: AriaTextConfig, layer_idx: int):
|
| 808 |
+
super().__init__(config, layer_idx)
|
| 809 |
+
self.mlp = AriaTextMoELayer(config)
|
| 810 |
+
|
| 811 |
+
|
| 812 |
+
@auto_docstring
|
| 813 |
+
class AriaTextPreTrainedModel(PreTrainedModel):
|
| 814 |
+
config: AriaTextConfig
|
| 815 |
+
base_model_prefix = "model"
|
| 816 |
+
input_modalities = ("image", "text")
|
| 817 |
+
_no_split_modules = ["AriaTextDecoderLayer", "AriaGroupedExpertsGemm"]
|
| 818 |
+
supports_gradient_checkpointing = True
|
| 819 |
+
_skip_keys_device_placement = ["past_key_values"]
|
| 820 |
+
_supports_flash_attn = True
|
| 821 |
+
_supports_sdpa = True
|
| 822 |
+
|
| 823 |
+
_supports_attention_backend = True
|
| 824 |
+
_can_record_outputs = {
|
| 825 |
+
"hidden_states": AriaTextDecoderLayer,
|
| 826 |
+
"attentions": AriaTextAttention,
|
| 827 |
+
}
|
| 828 |
+
|
| 829 |
+
@torch.no_grad()
|
| 830 |
+
def _init_weights(self, module):
|
| 831 |
+
super()._init_weights(module)
|
| 832 |
+
if isinstance(module, AriaGroupedExpertsGemm):
|
| 833 |
+
init.normal_(module.weight, mean=0.0, std=self.config.initializer_range)
|
| 834 |
+
|
| 835 |
+
|
| 836 |
+
class AriaPreTrainedModel(LlamaPreTrainedModel):
|
| 837 |
+
config: AriaConfig
|
| 838 |
+
base_model_prefix = "model"
|
| 839 |
+
_can_compile_fullgraph = False # MoE models don't work with torch.compile (dynamic slicing)
|
| 840 |
+
_supports_attention_backend = True
|
| 841 |
+
|
| 842 |
+
@torch.no_grad()
|
| 843 |
+
def _init_weights(self, module):
|
| 844 |
+
PreTrainedModel._init_weights(self, module)
|
| 845 |
+
if isinstance(module, AriaProjector):
|
| 846 |
+
init.trunc_normal_(module.query, std=self.config.initializer_range)
|
| 847 |
+
|
| 848 |
+
|
| 849 |
+
class AriaTextModel(LlamaModel):
|
| 850 |
+
def __init__(self, config: AriaTextConfig):
|
| 851 |
+
super().__init__(config)
|
| 852 |
+
self.layers = nn.ModuleList(
|
| 853 |
+
[AriaTextDecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 854 |
+
)
|
| 855 |
+
self.gradient_checkpointing = False
|
| 856 |
+
self.post_init()
|
| 857 |
+
|
| 858 |
+
|
| 859 |
+
class AriaTextForCausalLM(AriaTextPreTrainedModel, LlamaForCausalLM):
|
| 860 |
+
_tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
|
| 861 |
+
|
| 862 |
+
def __init__(self, config: AriaTextConfig):
|
| 863 |
+
super().__init__(config)
|
| 864 |
+
self.model = AriaTextModel(config)
|
| 865 |
+
self.vocab_size = config.vocab_size
|
| 866 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 867 |
+
|
| 868 |
+
# Initialize weights and apply final processing
|
| 869 |
+
self.post_init()
|
| 870 |
+
|
| 871 |
+
@auto_docstring
|
| 872 |
+
def forward(self, **super_kwargs):
|
| 873 |
+
super().forward(self, **super_kwargs)
|
| 874 |
+
|
| 875 |
+
|
| 876 |
+
class AriaCausalLMOutputWithPast(LlavaCausalLMOutputWithPast):
|
| 877 |
+
pass
|
| 878 |
+
|
| 879 |
+
|
| 880 |
+
class AriaModelOutputWithPast(LlavaModelOutputWithPast):
|
| 881 |
+
pass
|
| 882 |
+
|
| 883 |
+
|
| 884 |
+
class AriaModel(LlavaModel):
|
| 885 |
+
def __init__(self, config: AriaConfig):
|
| 886 |
+
super().__init__(config)
|
| 887 |
+
self.multi_modal_projector = AriaProjector(config)
|
| 888 |
+
|
| 889 |
+
def _create_patch_attention_mask(self, pixel_mask):
|
| 890 |
+
if pixel_mask is None:
|
| 891 |
+
return None
|
| 892 |
+
|
| 893 |
+
patches_subgrid = pixel_mask.unfold(
|
| 894 |
+
dimension=1,
|
| 895 |
+
size=self.vision_tower.config.patch_size,
|
| 896 |
+
step=self.vision_tower.config.patch_size,
|
| 897 |
+
)
|
| 898 |
+
patches_subgrid = patches_subgrid.unfold(
|
| 899 |
+
dimension=2,
|
| 900 |
+
size=self.vision_tower.config.patch_size,
|
| 901 |
+
step=self.vision_tower.config.patch_size,
|
| 902 |
+
)
|
| 903 |
+
return (patches_subgrid.sum(dim=(-1, -2)) > 0).bool()
|
| 904 |
+
|
| 905 |
+
def get_image_features(
|
| 906 |
+
self,
|
| 907 |
+
pixel_values: torch.FloatTensor,
|
| 908 |
+
pixel_mask: torch.FloatTensor | None = None,
|
| 909 |
+
vision_feature_layer: int | list[int] = -1,
|
| 910 |
+
output_hidden_states: bool | None = None,
|
| 911 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 912 |
+
) -> tuple | BaseModelOutputWithPooling:
|
| 913 |
+
patch_attention_mask = self._create_patch_attention_mask(pixel_mask)
|
| 914 |
+
image_outputs = self.vision_tower(
|
| 915 |
+
pixel_values,
|
| 916 |
+
patch_attention_mask=patch_attention_mask,
|
| 917 |
+
output_hidden_states=True, # Ignore arg on purpose
|
| 918 |
+
return_dict=True,
|
| 919 |
+
**kwargs,
|
| 920 |
+
)
|
| 921 |
+
image_attn_mask = None
|
| 922 |
+
if patch_attention_mask is not None:
|
| 923 |
+
flattened_mask = patch_attention_mask.flatten(1)
|
| 924 |
+
image_attn_mask = torch.logical_not(flattened_mask)
|
| 925 |
+
|
| 926 |
+
selected_image_feature = image_outputs.hidden_states[vision_feature_layer]
|
| 927 |
+
image_outputs.pooler_output = self.multi_modal_projector(selected_image_feature, attn_mask=image_attn_mask)
|
| 928 |
+
|
| 929 |
+
return image_outputs
|
| 930 |
+
|
| 931 |
+
def forward(
|
| 932 |
+
self,
|
| 933 |
+
input_ids: torch.LongTensor | None = None,
|
| 934 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 935 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 936 |
+
attention_mask: torch.Tensor | None = None,
|
| 937 |
+
position_ids: torch.LongTensor | None = None,
|
| 938 |
+
past_key_values: Cache | None = None,
|
| 939 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 940 |
+
use_cache: bool | None = None,
|
| 941 |
+
**kwargs: Unpack[FlashAttentionKwargs],
|
| 942 |
+
) -> tuple | AriaModelOutputWithPast:
|
| 943 |
+
if inputs_embeds is None:
|
| 944 |
+
inputs_embeds = self.get_input_embeddings()(input_ids)
|
| 945 |
+
|
| 946 |
+
# 2. Merge text and images
|
| 947 |
+
if pixel_values is not None and inputs_embeds.shape[1] != 1:
|
| 948 |
+
image_features = self.get_image_features(
|
| 949 |
+
pixel_values=pixel_values,
|
| 950 |
+
pixel_mask=pixel_mask,
|
| 951 |
+
vision_feature_layer=self.config.vision_feature_layer,
|
| 952 |
+
return_dict=True,
|
| 953 |
+
).pooler_output
|
| 954 |
+
image_features = image_features.to(inputs_embeds.device, inputs_embeds.dtype)
|
| 955 |
+
special_image_mask = self.get_placeholder_mask(
|
| 956 |
+
input_ids, inputs_embeds=inputs_embeds, image_features=image_features
|
| 957 |
+
)
|
| 958 |
+
inputs_embeds = inputs_embeds.masked_scatter(special_image_mask, image_features)
|
| 959 |
+
|
| 960 |
+
outputs = self.language_model(
|
| 961 |
+
attention_mask=attention_mask,
|
| 962 |
+
position_ids=position_ids,
|
| 963 |
+
past_key_values=past_key_values,
|
| 964 |
+
inputs_embeds=inputs_embeds,
|
| 965 |
+
use_cache=use_cache,
|
| 966 |
+
**kwargs,
|
| 967 |
+
)
|
| 968 |
+
|
| 969 |
+
return AriaModelOutputWithPast(
|
| 970 |
+
last_hidden_state=outputs.last_hidden_state,
|
| 971 |
+
past_key_values=outputs.past_key_values if use_cache else None,
|
| 972 |
+
hidden_states=outputs.hidden_states,
|
| 973 |
+
attentions=outputs.attentions,
|
| 974 |
+
image_hidden_states=image_features if pixel_values is not None else None,
|
| 975 |
+
)
|
| 976 |
+
|
| 977 |
+
|
| 978 |
+
@auto_docstring(
|
| 979 |
+
custom_intro="""
|
| 980 |
+
Aria model for conditional generation tasks.
|
| 981 |
+
|
| 982 |
+
This model combines a vision tower, a multi-modal projector, and a language model
|
| 983 |
+
to perform tasks that involve both image and text inputs.
|
| 984 |
+
"""
|
| 985 |
+
)
|
| 986 |
+
class AriaForConditionalGeneration(LlavaForConditionalGeneration):
|
| 987 |
+
_tied_weights_keys = {"lm_head.weight": "model.language_model.embed_tokens.weight"}
|
| 988 |
+
|
| 989 |
+
@auto_docstring
|
| 990 |
+
def get_image_features(
|
| 991 |
+
self,
|
| 992 |
+
pixel_values: torch.FloatTensor,
|
| 993 |
+
pixel_mask: torch.FloatTensor | None = None,
|
| 994 |
+
vision_feature_layer: int | list[int] = -1,
|
| 995 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 996 |
+
) -> tuple | BaseModelOutputWithPooling:
|
| 997 |
+
return self.model.get_image_features(
|
| 998 |
+
pixel_values=pixel_values,
|
| 999 |
+
pixel_mask=pixel_mask,
|
| 1000 |
+
vision_feature_layer=vision_feature_layer,
|
| 1001 |
+
**kwargs,
|
| 1002 |
+
)
|
| 1003 |
+
|
| 1004 |
+
@can_return_tuple
|
| 1005 |
+
@auto_docstring
|
| 1006 |
+
def forward(
|
| 1007 |
+
self,
|
| 1008 |
+
input_ids: torch.LongTensor | None = None,
|
| 1009 |
+
pixel_values: torch.FloatTensor | None = None,
|
| 1010 |
+
pixel_mask: torch.LongTensor | None = None,
|
| 1011 |
+
attention_mask: torch.Tensor | None = None,
|
| 1012 |
+
position_ids: torch.LongTensor | None = None,
|
| 1013 |
+
past_key_values: Cache | None = None,
|
| 1014 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 1015 |
+
labels: torch.LongTensor | None = None,
|
| 1016 |
+
use_cache: bool | None = None,
|
| 1017 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 1018 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 1019 |
+
) -> tuple | AriaCausalLMOutputWithPast:
|
| 1020 |
+
r"""
|
| 1021 |
+
labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 1022 |
+
Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
|
| 1023 |
+
config.vocab_size]` or `model.image_token_id` (where `model` is your instance of `AriaForConditionalGeneration`).
|
| 1024 |
+
Tokens with indices set to `model.image_token_id` are ignored (masked), the loss is only
|
| 1025 |
+
computed for the tokens with labels in `[0, ..., config.vocab_size]`.
|
| 1026 |
+
|
| 1027 |
+
Example:
|
| 1028 |
+
|
| 1029 |
+
```python
|
| 1030 |
+
>>> import httpx
|
| 1031 |
+
>>> from io import BytesIO
|
| 1032 |
+
>>> import torch
|
| 1033 |
+
>>> from PIL import Image
|
| 1034 |
+
>>> from io import BytesIO
|
| 1035 |
+
|
| 1036 |
+
>>> from transformers import AutoProcessor, AutoModel
|
| 1037 |
+
>>> from transformers.image_utils import load_image
|
| 1038 |
+
|
| 1039 |
+
>>> # Note that passing the image urls (instead of the actual pil images) to the processor is also possible
|
| 1040 |
+
>>> image1 = load_image("https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg")
|
| 1041 |
+
>>> image2 = load_image("https://cdn.britannica.com/59/94459-050-DBA42467/Skyline-Chicago.jpg")
|
| 1042 |
+
>>> image3 = load_image("https://cdn.britannica.com/68/170868-050-8DDE8263/Golden-Gate-Bridge-San-Francisco.jpg")
|
| 1043 |
+
|
| 1044 |
+
>>> processor = AutoProcessor.from_pretrained("Rhymes-AI/Aria")
|
| 1045 |
+
>>> model = AutoModel.from_pretrained("Rhymes-AI/Aria", dtype=torch.bfloat16, device_map="auto")
|
| 1046 |
+
|
| 1047 |
+
>>> # Create inputs
|
| 1048 |
+
>>> messages = [
|
| 1049 |
+
... {
|
| 1050 |
+
... "role": "user",
|
| 1051 |
+
... "content": [
|
| 1052 |
+
... {"type": "image"},
|
| 1053 |
+
... {"type": "text", "text": "In this image, we can see the city of New York, and more specifically the Statue of Liberty."},
|
| 1054 |
+
... {"type": "image"},
|
| 1055 |
+
... {"type": "text", "text": "What can we see in this image?"},
|
| 1056 |
+
... ]
|
| 1057 |
+
... },
|
| 1058 |
+
... {
|
| 1059 |
+
... "role": "user",
|
| 1060 |
+
... "content": [
|
| 1061 |
+
... {"type": "image"},
|
| 1062 |
+
... {"type": "text", "text": "In which city is that bridge located?"},
|
| 1063 |
+
... ]
|
| 1064 |
+
... }
|
| 1065 |
+
... ]
|
| 1066 |
+
|
| 1067 |
+
>>> prompts = [processor.apply_chat_template([message], add_generation_prompt=True) for message in messages]
|
| 1068 |
+
>>> images = [[image1, image2], [image3]]
|
| 1069 |
+
>>> inputs = processor(text=prompts, images=images, padding=True, return_tensors="pt").to(model.device)
|
| 1070 |
+
|
| 1071 |
+
>>> # Generate
|
| 1072 |
+
>>> generated_ids = model.generate(**inputs, max_new_tokens=256)
|
| 1073 |
+
>>> generated_texts = processor.batch_decode(generated_ids, skip_special_tokens=True)
|
| 1074 |
+
|
| 1075 |
+
>>> print(generated_texts[0])
|
| 1076 |
+
Assistant: There are buildings, trees, lights, and water visible in this image.
|
| 1077 |
+
|
| 1078 |
+
>>> print(generated_texts[1])
|
| 1079 |
+
Assistant: The bridge is in San Francisco.
|
| 1080 |
+
```"""
|
| 1081 |
+
outputs = self.model(
|
| 1082 |
+
input_ids=input_ids,
|
| 1083 |
+
pixel_values=pixel_values,
|
| 1084 |
+
pixel_mask=pixel_mask,
|
| 1085 |
+
attention_mask=attention_mask,
|
| 1086 |
+
position_ids=position_ids,
|
| 1087 |
+
past_key_values=past_key_values,
|
| 1088 |
+
inputs_embeds=inputs_embeds,
|
| 1089 |
+
use_cache=use_cache,
|
| 1090 |
+
**kwargs,
|
| 1091 |
+
)
|
| 1092 |
+
|
| 1093 |
+
hidden_states = outputs[0]
|
| 1094 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 1095 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 1096 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 1097 |
+
|
| 1098 |
+
loss = None
|
| 1099 |
+
if labels is not None:
|
| 1100 |
+
loss = self.loss_function(
|
| 1101 |
+
logits=logits, labels=labels, vocab_size=self.config.text_config.vocab_size, **kwargs
|
| 1102 |
+
)
|
| 1103 |
+
|
| 1104 |
+
return AriaCausalLMOutputWithPast(
|
| 1105 |
+
loss=loss,
|
| 1106 |
+
logits=logits,
|
| 1107 |
+
past_key_values=outputs.past_key_values,
|
| 1108 |
+
hidden_states=outputs.hidden_states,
|
| 1109 |
+
attentions=outputs.attentions,
|
| 1110 |
+
)
|
| 1111 |
+
|
| 1112 |
+
def prepare_inputs_for_generation(
|
| 1113 |
+
self,
|
| 1114 |
+
input_ids,
|
| 1115 |
+
past_key_values=None,
|
| 1116 |
+
inputs_embeds=None,
|
| 1117 |
+
pixel_values=None,
|
| 1118 |
+
pixel_mask=None,
|
| 1119 |
+
attention_mask=None,
|
| 1120 |
+
logits_to_keep=None,
|
| 1121 |
+
is_first_iteration=False,
|
| 1122 |
+
**kwargs,
|
| 1123 |
+
):
|
| 1124 |
+
model_inputs = super().prepare_inputs_for_generation(
|
| 1125 |
+
input_ids,
|
| 1126 |
+
past_key_values=past_key_values,
|
| 1127 |
+
inputs_embeds=inputs_embeds,
|
| 1128 |
+
attention_mask=attention_mask,
|
| 1129 |
+
logits_to_keep=logits_to_keep,
|
| 1130 |
+
is_first_iteration=is_first_iteration,
|
| 1131 |
+
**kwargs,
|
| 1132 |
+
)
|
| 1133 |
+
|
| 1134 |
+
if is_first_iteration or not kwargs.get("use_cache", True):
|
| 1135 |
+
# Pixel values are used only in the first iteration if available
|
| 1136 |
+
# In subsequent iterations, they are already merged with text and cached
|
| 1137 |
+
# NOTE: first iteration doesn't have to be prefill, it can be the first
|
| 1138 |
+
# iteration with a question and cached system prompt (continue generate from cache)
|
| 1139 |
+
model_inputs["pixel_values"] = pixel_values
|
| 1140 |
+
model_inputs["pixel_mask"] = pixel_mask
|
| 1141 |
+
|
| 1142 |
+
return model_inputs
|
| 1143 |
+
|
| 1144 |
+
|
| 1145 |
+
__all__ = [
|
| 1146 |
+
"AriaConfig",
|
| 1147 |
+
"AriaTextConfig",
|
| 1148 |
+
"AriaImageProcessor",
|
| 1149 |
+
"AriaProcessor",
|
| 1150 |
+
"AriaForConditionalGeneration",
|
| 1151 |
+
"AriaPreTrainedModel",
|
| 1152 |
+
"AriaTextPreTrainedModel",
|
| 1153 |
+
"AriaTextModel",
|
| 1154 |
+
"AriaModel",
|
| 1155 |
+
"AriaTextForCausalLM",
|
| 1156 |
+
]
|
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/timesformer/modeling_timesformer.py
ADDED
|
@@ -0,0 +1,751 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2022 Meta and The HuggingFace Inc. team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""PyTorch TimeSformer model."""
|
| 15 |
+
|
| 16 |
+
import collections
|
| 17 |
+
|
| 18 |
+
import torch
|
| 19 |
+
from torch import nn
|
| 20 |
+
from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss
|
| 21 |
+
|
| 22 |
+
from ... import initialization as init
|
| 23 |
+
from ...activations import ACT2FN
|
| 24 |
+
from ...modeling_layers import GradientCheckpointingLayer
|
| 25 |
+
from ...modeling_outputs import BaseModelOutput, ImageClassifierOutput
|
| 26 |
+
from ...modeling_utils import PreTrainedModel
|
| 27 |
+
from ...utils import (
|
| 28 |
+
auto_docstring,
|
| 29 |
+
logging,
|
| 30 |
+
)
|
| 31 |
+
from .configuration_timesformer import TimesformerConfig
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
logger = logging.get_logger(__name__)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# Adapted from https://github.com/facebookresearch/TimeSformer/blob/a5ef29a7b7264baff199a30b3306ac27de901133/timesformer/models/vit.py#L155
|
| 38 |
+
class TimesformerPatchEmbeddings(nn.Module):
|
| 39 |
+
"""Image to Patch Embedding"""
|
| 40 |
+
|
| 41 |
+
def __init__(self, config):
|
| 42 |
+
super().__init__()
|
| 43 |
+
|
| 44 |
+
image_size = config.image_size
|
| 45 |
+
patch_size = config.patch_size
|
| 46 |
+
|
| 47 |
+
image_size = image_size if isinstance(image_size, collections.abc.Iterable) else (image_size, image_size)
|
| 48 |
+
patch_size = patch_size if isinstance(patch_size, collections.abc.Iterable) else (patch_size, patch_size)
|
| 49 |
+
|
| 50 |
+
num_patches = (image_size[1] // patch_size[1]) * (image_size[0] // patch_size[0])
|
| 51 |
+
self.image_size = image_size
|
| 52 |
+
self.patch_size = patch_size
|
| 53 |
+
self.num_patches = num_patches
|
| 54 |
+
|
| 55 |
+
self.projection = nn.Conv2d(config.num_channels, config.hidden_size, kernel_size=patch_size, stride=patch_size)
|
| 56 |
+
|
| 57 |
+
def forward(self, pixel_values):
|
| 58 |
+
batch_size, num_frames, num_channels, height, width = pixel_values.shape
|
| 59 |
+
pixel_values = pixel_values.reshape(batch_size * num_frames, num_channels, height, width)
|
| 60 |
+
|
| 61 |
+
embeddings = self.projection(pixel_values)
|
| 62 |
+
patch_width = embeddings.size(-1)
|
| 63 |
+
embeddings = embeddings.flatten(2).transpose(1, 2)
|
| 64 |
+
return embeddings, num_frames, patch_width
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
class TimesformerEmbeddings(nn.Module):
|
| 68 |
+
"""
|
| 69 |
+
Construct the patch and position embeddings.
|
| 70 |
+
"""
|
| 71 |
+
|
| 72 |
+
def __init__(self, config):
|
| 73 |
+
super().__init__()
|
| 74 |
+
|
| 75 |
+
embed_dim = config.hidden_size
|
| 76 |
+
num_frames = config.num_frames
|
| 77 |
+
drop_rate = config.hidden_dropout_prob
|
| 78 |
+
attention_type = config.attention_type
|
| 79 |
+
|
| 80 |
+
self.attention_type = attention_type
|
| 81 |
+
self.patch_embeddings = TimesformerPatchEmbeddings(config)
|
| 82 |
+
self.num_patches = self.patch_embeddings.num_patches
|
| 83 |
+
|
| 84 |
+
# Positional Embeddings
|
| 85 |
+
self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))
|
| 86 |
+
self.position_embeddings = nn.Parameter(torch.zeros(1, self.num_patches + 1, embed_dim))
|
| 87 |
+
self.pos_drop = nn.Dropout(p=drop_rate)
|
| 88 |
+
if attention_type != "space_only":
|
| 89 |
+
self.time_embeddings = nn.Parameter(torch.zeros(1, num_frames, embed_dim))
|
| 90 |
+
self.time_drop = nn.Dropout(p=drop_rate)
|
| 91 |
+
|
| 92 |
+
def forward(self, pixel_values):
|
| 93 |
+
batch_size = pixel_values.shape[0]
|
| 94 |
+
|
| 95 |
+
# create patch embeddings
|
| 96 |
+
embeddings, num_frames, patch_width = self.patch_embeddings(pixel_values)
|
| 97 |
+
|
| 98 |
+
cls_tokens = self.cls_token.expand(embeddings.size(0), -1, -1)
|
| 99 |
+
embeddings = torch.cat((cls_tokens, embeddings), dim=1)
|
| 100 |
+
|
| 101 |
+
# resizing the positional embeddings in case they don't match the input at inference
|
| 102 |
+
if embeddings.size(1) != self.position_embeddings.size(1):
|
| 103 |
+
position_embeddings = self.position_embeddings
|
| 104 |
+
cls_pos_embed = position_embeddings[0, 0, :].unsqueeze(0).unsqueeze(1)
|
| 105 |
+
other_pos_embed = position_embeddings[0, 1:, :].unsqueeze(0).transpose(1, 2)
|
| 106 |
+
patch_num = int(other_pos_embed.size(2) ** 0.5)
|
| 107 |
+
patch_height = embeddings.size(1) // patch_width
|
| 108 |
+
other_pos_embed = other_pos_embed.reshape(1, embeddings.size(2), patch_num, patch_num)
|
| 109 |
+
new_pos_embed = nn.functional.interpolate(
|
| 110 |
+
other_pos_embed, size=(patch_height, patch_width), mode="nearest"
|
| 111 |
+
)
|
| 112 |
+
new_pos_embed = new_pos_embed.flatten(2)
|
| 113 |
+
new_pos_embed = new_pos_embed.transpose(1, 2)
|
| 114 |
+
new_pos_embed = torch.cat((cls_pos_embed, new_pos_embed), 1)
|
| 115 |
+
embeddings = embeddings + new_pos_embed
|
| 116 |
+
else:
|
| 117 |
+
embeddings = embeddings + self.position_embeddings
|
| 118 |
+
embeddings = self.pos_drop(embeddings)
|
| 119 |
+
|
| 120 |
+
# Time Embeddings
|
| 121 |
+
if self.attention_type != "space_only":
|
| 122 |
+
cls_tokens = embeddings[:batch_size, 0, :].unsqueeze(1)
|
| 123 |
+
embeddings = embeddings[:, 1:]
|
| 124 |
+
_, patch_height, patch_width = embeddings.shape
|
| 125 |
+
embeddings = (
|
| 126 |
+
embeddings.reshape(batch_size, num_frames, patch_height, patch_width)
|
| 127 |
+
.permute(0, 2, 1, 3)
|
| 128 |
+
.reshape(batch_size * patch_height, num_frames, patch_width)
|
| 129 |
+
)
|
| 130 |
+
# Resizing time embeddings in case they don't match
|
| 131 |
+
if num_frames != self.time_embeddings.size(1):
|
| 132 |
+
time_embeddings = self.time_embeddings.transpose(1, 2)
|
| 133 |
+
new_time_embeddings = nn.functional.interpolate(time_embeddings, size=(num_frames), mode="nearest")
|
| 134 |
+
new_time_embeddings = new_time_embeddings.transpose(1, 2)
|
| 135 |
+
embeddings = embeddings + new_time_embeddings
|
| 136 |
+
else:
|
| 137 |
+
embeddings = embeddings + self.time_embeddings
|
| 138 |
+
embeddings = self.time_drop(embeddings)
|
| 139 |
+
embeddings = embeddings.view(batch_size, patch_height, num_frames, patch_width).reshape(
|
| 140 |
+
batch_size, patch_height * num_frames, patch_width
|
| 141 |
+
)
|
| 142 |
+
embeddings = torch.cat((cls_tokens, embeddings), dim=1)
|
| 143 |
+
|
| 144 |
+
return embeddings
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
# Adapted from https://github.com/facebookresearch/TimeSformer/blob/a5ef29a7b7264baff199a30b3306ac27de901133/timesformer/models/vit.py#L57
|
| 148 |
+
class TimesformerSelfAttention(nn.Module):
|
| 149 |
+
def __init__(self, config: TimesformerConfig):
|
| 150 |
+
super().__init__()
|
| 151 |
+
|
| 152 |
+
num_heads = config.num_attention_heads
|
| 153 |
+
qkv_bias = config.qkv_bias
|
| 154 |
+
attention_dropout_prob = config.attention_probs_dropout_prob
|
| 155 |
+
|
| 156 |
+
self.num_heads = num_heads
|
| 157 |
+
head_dim = config.hidden_size // num_heads
|
| 158 |
+
self.scale = head_dim**-0.5
|
| 159 |
+
self.qkv = nn.Linear(config.hidden_size, config.hidden_size * 3, bias=qkv_bias)
|
| 160 |
+
self.attn_drop = nn.Dropout(attention_dropout_prob)
|
| 161 |
+
|
| 162 |
+
def forward(self, hidden_states, output_attentions: bool = False):
|
| 163 |
+
batch_size, hidden_size, num_channels = hidden_states.shape
|
| 164 |
+
qkv = (
|
| 165 |
+
self.qkv(hidden_states)
|
| 166 |
+
.reshape(batch_size, hidden_size, 3, self.num_heads, num_channels // self.num_heads)
|
| 167 |
+
.permute(2, 0, 3, 1, 4)
|
| 168 |
+
)
|
| 169 |
+
query, key, value = qkv[0], qkv[1], qkv[2]
|
| 170 |
+
|
| 171 |
+
attention_probs = (query @ key.transpose(-2, -1)) * self.scale
|
| 172 |
+
attention_probs = attention_probs.softmax(dim=-1)
|
| 173 |
+
attention_probs = self.attn_drop(attention_probs)
|
| 174 |
+
|
| 175 |
+
context_layer = (attention_probs @ value).transpose(1, 2).reshape(batch_size, hidden_size, num_channels)
|
| 176 |
+
|
| 177 |
+
outputs = (context_layer, attention_probs) if output_attentions else (context_layer,)
|
| 178 |
+
|
| 179 |
+
return outputs
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
class TimesformerSelfOutput(nn.Module):
|
| 183 |
+
"""
|
| 184 |
+
The residual connection is defined in TimesformerLayer instead of here (as is the case with other models), due to
|
| 185 |
+
the layernorm applied before each block.
|
| 186 |
+
"""
|
| 187 |
+
|
| 188 |
+
def __init__(self, config: TimesformerConfig) -> None:
|
| 189 |
+
super().__init__()
|
| 190 |
+
self.dense = nn.Linear(config.hidden_size, config.hidden_size)
|
| 191 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 192 |
+
|
| 193 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 194 |
+
hidden_states = self.dense(hidden_states)
|
| 195 |
+
hidden_states = self.dropout(hidden_states)
|
| 196 |
+
|
| 197 |
+
return hidden_states
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
class TimeSformerAttention(nn.Module):
|
| 201 |
+
def __init__(self, config: TimesformerConfig) -> None:
|
| 202 |
+
super().__init__()
|
| 203 |
+
self.attention = TimesformerSelfAttention(config)
|
| 204 |
+
self.output = TimesformerSelfOutput(config)
|
| 205 |
+
|
| 206 |
+
def forward(
|
| 207 |
+
self,
|
| 208 |
+
hidden_states: torch.Tensor,
|
| 209 |
+
output_attentions: bool = False,
|
| 210 |
+
) -> tuple[torch.Tensor, torch.Tensor] | tuple[torch.Tensor]:
|
| 211 |
+
self_outputs = self.attention(hidden_states, output_attentions)
|
| 212 |
+
|
| 213 |
+
attention_output = self.output(self_outputs[0])
|
| 214 |
+
|
| 215 |
+
outputs = (attention_output,) + self_outputs[1:] # add attentions if we output them
|
| 216 |
+
return outputs
|
| 217 |
+
|
| 218 |
+
|
| 219 |
+
# Adapted from https://github.com/facebookresearch/TimeSformer/blob/a5ef29a7b7264baff199a30b3306ac27de901133/timesformer/models/vit.py#L39
|
| 220 |
+
class TimesformerIntermediate(nn.Module):
|
| 221 |
+
def __init__(self, config: TimesformerConfig) -> None:
|
| 222 |
+
super().__init__()
|
| 223 |
+
self.dense = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 224 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 225 |
+
|
| 226 |
+
if isinstance(config.hidden_act, str):
|
| 227 |
+
self.intermediate_act_fn = ACT2FN[config.hidden_act]
|
| 228 |
+
else:
|
| 229 |
+
self.intermediate_act_fn = config.hidden_act
|
| 230 |
+
|
| 231 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 232 |
+
hidden_states = self.dense(hidden_states)
|
| 233 |
+
hidden_states = self.intermediate_act_fn(hidden_states)
|
| 234 |
+
hidden_states = self.dropout(hidden_states)
|
| 235 |
+
|
| 236 |
+
return hidden_states
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
class TimesformerOutput(nn.Module):
|
| 240 |
+
def __init__(self, config: TimesformerConfig) -> None:
|
| 241 |
+
super().__init__()
|
| 242 |
+
self.dense = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 243 |
+
self.dropout = nn.Dropout(config.hidden_dropout_prob)
|
| 244 |
+
|
| 245 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 246 |
+
hidden_states = self.dense(hidden_states)
|
| 247 |
+
hidden_states = self.dropout(hidden_states)
|
| 248 |
+
|
| 249 |
+
return hidden_states
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
# Copied from transformers.models.swin.modular_swin.SwinDropPath with SwinDropPath->TimesformerDropPath
|
| 253 |
+
class TimesformerDropPath(nn.Module):
|
| 254 |
+
"""Stochastic depth (DropPath) per sample, for residual blocks.
|
| 255 |
+
|
| 256 |
+
Identity when ``drop_prob`` is 0 or outside training. See `Deep Networks with Stochastic Depth
|
| 257 |
+
<https://arxiv.org/abs/1603.09382>`_.
|
| 258 |
+
"""
|
| 259 |
+
|
| 260 |
+
def __init__(self, drop_prob: float = 0.0) -> None:
|
| 261 |
+
super().__init__()
|
| 262 |
+
self.drop_prob = drop_prob
|
| 263 |
+
|
| 264 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 265 |
+
if self.drop_prob == 0.0 or not self.training:
|
| 266 |
+
return hidden_states
|
| 267 |
+
keep_prob = 1 - self.drop_prob
|
| 268 |
+
shape = (hidden_states.shape[0],) + (1,) * (hidden_states.ndim - 1)
|
| 269 |
+
random_tensor = torch.rand(shape, dtype=hidden_states.dtype, device=hidden_states.device)
|
| 270 |
+
random_tensor = torch.floor(random_tensor + keep_prob)
|
| 271 |
+
return hidden_states.div(keep_prob) * random_tensor
|
| 272 |
+
|
| 273 |
+
def extra_repr(self) -> str:
|
| 274 |
+
return f"p={self.drop_prob}"
|
| 275 |
+
|
| 276 |
+
|
| 277 |
+
# Adapted from https://github.com/facebookresearch/TimeSformer/blob/a5ef29a7b7264baff199a30b3306ac27de901133/timesformer/models/vit.py#L89
|
| 278 |
+
class TimesformerLayer(GradientCheckpointingLayer):
|
| 279 |
+
def __init__(self, config: TimesformerConfig, layer_index: int) -> None:
|
| 280 |
+
super().__init__()
|
| 281 |
+
|
| 282 |
+
attention_type = config.attention_type
|
| 283 |
+
|
| 284 |
+
drop_path_rates = [
|
| 285 |
+
x.item() for x in torch.linspace(0, config.drop_path_rate, config.num_hidden_layers, device="cpu")
|
| 286 |
+
] # stochastic depth decay rule
|
| 287 |
+
drop_path_rate = drop_path_rates[layer_index]
|
| 288 |
+
|
| 289 |
+
self.drop_path = TimesformerDropPath(drop_path_rate) if drop_path_rate > 0.0 else nn.Identity()
|
| 290 |
+
self.attention = TimeSformerAttention(config)
|
| 291 |
+
self.intermediate = TimesformerIntermediate(config)
|
| 292 |
+
self.output = TimesformerOutput(config)
|
| 293 |
+
self.layernorm_before = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 294 |
+
self.layernorm_after = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 295 |
+
|
| 296 |
+
self.config = config
|
| 297 |
+
self.attention_type = attention_type
|
| 298 |
+
if attention_type not in ["divided_space_time", "space_only", "joint_space_time"]:
|
| 299 |
+
raise ValueError(f"Unknown attention type: {attention_type}")
|
| 300 |
+
|
| 301 |
+
# Temporal Attention Parameters
|
| 302 |
+
if self.attention_type == "divided_space_time":
|
| 303 |
+
self.temporal_layernorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 304 |
+
self.temporal_attention = TimeSformerAttention(config)
|
| 305 |
+
self.temporal_dense = nn.Linear(config.hidden_size, config.hidden_size)
|
| 306 |
+
|
| 307 |
+
def forward(self, hidden_states: torch.Tensor, output_attentions: bool = False):
|
| 308 |
+
num_frames = self.config.num_frames
|
| 309 |
+
num_patch_width = self.config.image_size // self.config.patch_size
|
| 310 |
+
batch_size = hidden_states.shape[0]
|
| 311 |
+
num_spatial_tokens = (hidden_states.size(1) - 1) // num_frames
|
| 312 |
+
num_patch_height = num_spatial_tokens // num_patch_width
|
| 313 |
+
|
| 314 |
+
if self.attention_type in ["space_only", "joint_space_time"]:
|
| 315 |
+
self_attention_outputs = self.attention(
|
| 316 |
+
self.layernorm_before(hidden_states), output_attentions=output_attentions
|
| 317 |
+
)
|
| 318 |
+
attention_output = self_attention_outputs[0]
|
| 319 |
+
outputs = self_attention_outputs[1:] # add self attentions if we output attention weights
|
| 320 |
+
|
| 321 |
+
hidden_states = hidden_states + self.drop_path(attention_output)
|
| 322 |
+
|
| 323 |
+
layer_output = self.layernorm_after(hidden_states)
|
| 324 |
+
layer_output = self.intermediate(layer_output)
|
| 325 |
+
layer_output = self.output(layer_output)
|
| 326 |
+
layer_output = hidden_states + self.drop_path(layer_output)
|
| 327 |
+
|
| 328 |
+
outputs = (layer_output,) + outputs
|
| 329 |
+
|
| 330 |
+
return outputs
|
| 331 |
+
|
| 332 |
+
elif self.attention_type == "divided_space_time":
|
| 333 |
+
# Temporal
|
| 334 |
+
temporal_embedding = hidden_states[:, 1:, :]
|
| 335 |
+
temporal_embedding = temporal_embedding.reshape(
|
| 336 |
+
batch_size, num_patch_height, num_patch_width, num_frames, temporal_embedding.shape[2]
|
| 337 |
+
).reshape(batch_size * num_patch_height * num_patch_width, num_frames, temporal_embedding.shape[2])
|
| 338 |
+
|
| 339 |
+
temporal_attention_outputs = self.temporal_attention(
|
| 340 |
+
self.temporal_layernorm(temporal_embedding),
|
| 341 |
+
)
|
| 342 |
+
attention_output = temporal_attention_outputs[0]
|
| 343 |
+
|
| 344 |
+
residual_temporal = self.drop_path(attention_output)
|
| 345 |
+
|
| 346 |
+
residual_temporal = residual_temporal.reshape(
|
| 347 |
+
batch_size, num_patch_height, num_patch_width, num_frames, residual_temporal.shape[2]
|
| 348 |
+
).reshape(batch_size, num_patch_height * num_patch_width * num_frames, residual_temporal.shape[2])
|
| 349 |
+
residual_temporal = self.temporal_dense(residual_temporal)
|
| 350 |
+
temporal_embedding = hidden_states[:, 1:, :] + residual_temporal
|
| 351 |
+
|
| 352 |
+
# Spatial
|
| 353 |
+
init_cls_token = hidden_states[:, 0, :].unsqueeze(1)
|
| 354 |
+
cls_token = init_cls_token.repeat(1, num_frames, 1)
|
| 355 |
+
cls_token = cls_token.reshape(batch_size * num_frames, 1, cls_token.shape[2])
|
| 356 |
+
spatial_embedding = temporal_embedding
|
| 357 |
+
spatial_embedding = (
|
| 358 |
+
spatial_embedding.reshape(
|
| 359 |
+
batch_size, num_patch_height, num_patch_width, num_frames, spatial_embedding.shape[2]
|
| 360 |
+
)
|
| 361 |
+
.permute(0, 3, 1, 2, 4)
|
| 362 |
+
.reshape(batch_size * num_frames, num_patch_height * num_patch_width, spatial_embedding.shape[2])
|
| 363 |
+
)
|
| 364 |
+
spatial_embedding = torch.cat((cls_token, spatial_embedding), 1)
|
| 365 |
+
|
| 366 |
+
spatial_attention_outputs = self.attention(
|
| 367 |
+
self.layernorm_before(spatial_embedding), output_attentions=output_attentions
|
| 368 |
+
)
|
| 369 |
+
attention_output = spatial_attention_outputs[0]
|
| 370 |
+
outputs = spatial_attention_outputs[1:] # add self attentions if we output attention weights
|
| 371 |
+
|
| 372 |
+
residual_spatial = self.drop_path(attention_output)
|
| 373 |
+
|
| 374 |
+
# Taking care of CLS token
|
| 375 |
+
cls_token = residual_spatial[:, 0, :]
|
| 376 |
+
cls_token = cls_token.reshape(batch_size, num_frames, cls_token.shape[1])
|
| 377 |
+
cls_token = torch.mean(cls_token, 1, True) # averaging for every frame
|
| 378 |
+
residual_spatial = residual_spatial[:, 1:, :]
|
| 379 |
+
residual_spatial = (
|
| 380 |
+
residual_spatial.reshape(
|
| 381 |
+
batch_size, num_frames, num_patch_height, num_patch_width, residual_spatial.shape[2]
|
| 382 |
+
)
|
| 383 |
+
.permute(0, 2, 3, 1, 4)
|
| 384 |
+
.reshape(batch_size, num_patch_height * num_patch_width * num_frames, residual_spatial.shape[2])
|
| 385 |
+
)
|
| 386 |
+
residual = residual_spatial
|
| 387 |
+
hidden_states = temporal_embedding
|
| 388 |
+
|
| 389 |
+
# Mlp
|
| 390 |
+
hidden_states = torch.cat((init_cls_token, hidden_states), 1) + torch.cat((cls_token, residual), 1)
|
| 391 |
+
layer_output = self.layernorm_after(hidden_states)
|
| 392 |
+
layer_output = self.intermediate(layer_output)
|
| 393 |
+
layer_output = self.output(layer_output)
|
| 394 |
+
layer_output = hidden_states + self.drop_path(layer_output)
|
| 395 |
+
|
| 396 |
+
outputs = (layer_output,) + outputs
|
| 397 |
+
|
| 398 |
+
return outputs
|
| 399 |
+
|
| 400 |
+
|
| 401 |
+
class TimesformerEncoder(nn.Module):
|
| 402 |
+
def __init__(self, config: TimesformerConfig) -> None:
|
| 403 |
+
super().__init__()
|
| 404 |
+
self.config = config
|
| 405 |
+
self.layer = nn.ModuleList([TimesformerLayer(config, ind) for ind in range(config.num_hidden_layers)])
|
| 406 |
+
self.gradient_checkpointing = False
|
| 407 |
+
|
| 408 |
+
def forward(
|
| 409 |
+
self,
|
| 410 |
+
hidden_states: torch.Tensor,
|
| 411 |
+
output_attentions: bool = False,
|
| 412 |
+
output_hidden_states: bool = False,
|
| 413 |
+
return_dict: bool = True,
|
| 414 |
+
) -> tuple | BaseModelOutput:
|
| 415 |
+
all_hidden_states = () if output_hidden_states else None
|
| 416 |
+
all_self_attentions = () if output_attentions else None
|
| 417 |
+
|
| 418 |
+
for i, layer_module in enumerate(self.layer):
|
| 419 |
+
if output_hidden_states:
|
| 420 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 421 |
+
|
| 422 |
+
layer_outputs = layer_module(hidden_states, output_attentions)
|
| 423 |
+
|
| 424 |
+
hidden_states = layer_outputs[0]
|
| 425 |
+
|
| 426 |
+
if output_attentions:
|
| 427 |
+
all_self_attentions = all_self_attentions + (layer_outputs[1],)
|
| 428 |
+
|
| 429 |
+
if output_hidden_states:
|
| 430 |
+
all_hidden_states = all_hidden_states + (hidden_states,)
|
| 431 |
+
|
| 432 |
+
if not return_dict:
|
| 433 |
+
return tuple(v for v in [hidden_states, all_hidden_states, all_self_attentions] if v is not None)
|
| 434 |
+
return BaseModelOutput(
|
| 435 |
+
last_hidden_state=hidden_states,
|
| 436 |
+
hidden_states=all_hidden_states,
|
| 437 |
+
attentions=all_self_attentions,
|
| 438 |
+
)
|
| 439 |
+
|
| 440 |
+
|
| 441 |
+
@auto_docstring
|
| 442 |
+
class TimesformerPreTrainedModel(PreTrainedModel):
|
| 443 |
+
config: TimesformerConfig
|
| 444 |
+
base_model_prefix = "timesformer"
|
| 445 |
+
main_input_name = "pixel_values"
|
| 446 |
+
input_modalities = ("image",)
|
| 447 |
+
supports_gradient_checkpointing = True
|
| 448 |
+
_no_split_modules = ["TimesformerLayer"]
|
| 449 |
+
|
| 450 |
+
@torch.no_grad()
|
| 451 |
+
def _init_weights(self, module):
|
| 452 |
+
if isinstance(module, (nn.Linear, nn.Conv2d)):
|
| 453 |
+
init.trunc_normal_(module.weight, std=self.config.initializer_range)
|
| 454 |
+
if module.bias is not None:
|
| 455 |
+
init.constant_(module.bias, 0)
|
| 456 |
+
elif isinstance(module, nn.LayerNorm):
|
| 457 |
+
init.constant_(module.bias, 0)
|
| 458 |
+
init.constant_(module.weight, 1.0)
|
| 459 |
+
elif isinstance(module, TimesformerEmbeddings):
|
| 460 |
+
init.trunc_normal_(module.cls_token, std=self.config.initializer_range)
|
| 461 |
+
init.trunc_normal_(module.position_embeddings, std=self.config.initializer_range)
|
| 462 |
+
|
| 463 |
+
|
| 464 |
+
@auto_docstring
|
| 465 |
+
class TimesformerModel(TimesformerPreTrainedModel):
|
| 466 |
+
def __init__(self, config):
|
| 467 |
+
super().__init__(config)
|
| 468 |
+
self.config = config
|
| 469 |
+
|
| 470 |
+
self.embeddings = TimesformerEmbeddings(config)
|
| 471 |
+
self.encoder = TimesformerEncoder(config)
|
| 472 |
+
|
| 473 |
+
self.layernorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
|
| 474 |
+
|
| 475 |
+
# Initialize weights and apply final processing
|
| 476 |
+
self.post_init()
|
| 477 |
+
|
| 478 |
+
def get_input_embeddings(self):
|
| 479 |
+
return self.embeddings.patch_embeddings
|
| 480 |
+
|
| 481 |
+
@auto_docstring
|
| 482 |
+
def forward(
|
| 483 |
+
self,
|
| 484 |
+
pixel_values: torch.FloatTensor,
|
| 485 |
+
output_attentions: bool | None = None,
|
| 486 |
+
output_hidden_states: bool | None = None,
|
| 487 |
+
return_dict: bool | None = None,
|
| 488 |
+
**kwargs,
|
| 489 |
+
) -> tuple[torch.FloatTensor] | BaseModelOutput:
|
| 490 |
+
r"""
|
| 491 |
+
Examples:
|
| 492 |
+
|
| 493 |
+
```python
|
| 494 |
+
>>> import av
|
| 495 |
+
>>> import numpy as np
|
| 496 |
+
|
| 497 |
+
>>> from transformers import AutoImageProcessor, TimesformerModel
|
| 498 |
+
>>> from huggingface_hub import hf_hub_download
|
| 499 |
+
|
| 500 |
+
>>> np.random.seed(0)
|
| 501 |
+
|
| 502 |
+
|
| 503 |
+
>>> def read_video_pyav(container, indices):
|
| 504 |
+
... '''
|
| 505 |
+
... Decode the video with PyAV decoder.
|
| 506 |
+
... Args:
|
| 507 |
+
... container (`av.container.input.InputContainer`): PyAV container.
|
| 508 |
+
... indices (`list[int]`): List of frame indices to decode.
|
| 509 |
+
... Returns:
|
| 510 |
+
... result (np.ndarray): np array of decoded frames of shape (num_frames, height, width, 3).
|
| 511 |
+
... '''
|
| 512 |
+
... frames = []
|
| 513 |
+
... container.seek(0)
|
| 514 |
+
... start_index = indices[0]
|
| 515 |
+
... end_index = indices[-1]
|
| 516 |
+
... for i, frame in enumerate(container.decode(video=0)):
|
| 517 |
+
... if i > end_index:
|
| 518 |
+
... break
|
| 519 |
+
... if i >= start_index and i in indices:
|
| 520 |
+
... frames.append(frame)
|
| 521 |
+
... return np.stack([x.to_ndarray(format="rgb24") for x in frames])
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
>>> def sample_frame_indices(clip_len, frame_sample_rate, seg_len):
|
| 525 |
+
... '''
|
| 526 |
+
... Sample a given number of frame indices from the video.
|
| 527 |
+
... Args:
|
| 528 |
+
... clip_len (`int`): Total number of frames to sample.
|
| 529 |
+
... frame_sample_rate (`int`): Sample every n-th frame.
|
| 530 |
+
... seg_len (`int`): Maximum allowed index of sample's last frame.
|
| 531 |
+
... Returns:
|
| 532 |
+
... indices (`list[int]`): List of sampled frame indices
|
| 533 |
+
... '''
|
| 534 |
+
... converted_len = int(clip_len * frame_sample_rate)
|
| 535 |
+
... end_idx = np.random.randint(converted_len, seg_len)
|
| 536 |
+
... start_idx = end_idx - converted_len
|
| 537 |
+
... indices = np.linspace(start_idx, end_idx, num=clip_len)
|
| 538 |
+
... indices = np.clip(indices, start_idx, end_idx - 1).astype(np.int64)
|
| 539 |
+
... return indices
|
| 540 |
+
|
| 541 |
+
|
| 542 |
+
>>> # video clip consists of 300 frames (10 seconds at 30 FPS)
|
| 543 |
+
>>> file_path = hf_hub_download(
|
| 544 |
+
... repo_id="nielsr/video-demo", filename="eating_spaghetti.mp4", repo_type="dataset"
|
| 545 |
+
... )
|
| 546 |
+
>>> container = av.open(file_path)
|
| 547 |
+
|
| 548 |
+
>>> # sample 8 frames
|
| 549 |
+
>>> indices = sample_frame_indices(clip_len=8, frame_sample_rate=4, seg_len=container.streams.video[0].frames)
|
| 550 |
+
>>> video = read_video_pyav(container, indices)
|
| 551 |
+
|
| 552 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("MCG-NJU/videomae-base")
|
| 553 |
+
>>> model = TimesformerModel.from_pretrained("facebook/timesformer-base-finetuned-k400")
|
| 554 |
+
|
| 555 |
+
>>> # prepare video for the model
|
| 556 |
+
>>> inputs = image_processor(list(video), return_tensors="pt")
|
| 557 |
+
|
| 558 |
+
>>> # forward pass
|
| 559 |
+
>>> outputs = model(**inputs)
|
| 560 |
+
>>> last_hidden_states = outputs.last_hidden_state
|
| 561 |
+
>>> list(last_hidden_states.shape)
|
| 562 |
+
[1, 1569, 768]
|
| 563 |
+
```"""
|
| 564 |
+
output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
|
| 565 |
+
output_hidden_states = (
|
| 566 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 567 |
+
)
|
| 568 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 569 |
+
|
| 570 |
+
embedding_output = self.embeddings(pixel_values)
|
| 571 |
+
|
| 572 |
+
encoder_outputs = self.encoder(
|
| 573 |
+
embedding_output,
|
| 574 |
+
output_attentions=output_attentions,
|
| 575 |
+
output_hidden_states=output_hidden_states,
|
| 576 |
+
return_dict=return_dict,
|
| 577 |
+
)
|
| 578 |
+
sequence_output = encoder_outputs[0]
|
| 579 |
+
if self.layernorm is not None:
|
| 580 |
+
sequence_output = self.layernorm(sequence_output)
|
| 581 |
+
|
| 582 |
+
if not return_dict:
|
| 583 |
+
return (sequence_output,) + encoder_outputs[1:]
|
| 584 |
+
|
| 585 |
+
return BaseModelOutput(
|
| 586 |
+
last_hidden_state=sequence_output,
|
| 587 |
+
hidden_states=encoder_outputs.hidden_states,
|
| 588 |
+
attentions=encoder_outputs.attentions,
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
+
|
| 592 |
+
@auto_docstring(
|
| 593 |
+
custom_intro="""
|
| 594 |
+
TimeSformer Model transformer with a video classification head on top (a linear layer on top of the final hidden state
|
| 595 |
+
of the [CLS] token) e.g. for ImageNet.
|
| 596 |
+
"""
|
| 597 |
+
)
|
| 598 |
+
class TimesformerForVideoClassification(TimesformerPreTrainedModel):
|
| 599 |
+
def __init__(self, config):
|
| 600 |
+
super().__init__(config)
|
| 601 |
+
|
| 602 |
+
self.num_labels = config.num_labels
|
| 603 |
+
self.timesformer = TimesformerModel(config)
|
| 604 |
+
|
| 605 |
+
# Classifier head
|
| 606 |
+
self.classifier = nn.Linear(config.hidden_size, config.num_labels) if config.num_labels > 0 else nn.Identity()
|
| 607 |
+
|
| 608 |
+
# Initialize weights and apply final processing
|
| 609 |
+
self.post_init()
|
| 610 |
+
|
| 611 |
+
@auto_docstring
|
| 612 |
+
def forward(
|
| 613 |
+
self,
|
| 614 |
+
pixel_values: torch.Tensor | None = None,
|
| 615 |
+
labels: torch.Tensor | None = None,
|
| 616 |
+
output_attentions: bool | None = None,
|
| 617 |
+
output_hidden_states: bool | None = None,
|
| 618 |
+
return_dict: bool | None = None,
|
| 619 |
+
**kwargs,
|
| 620 |
+
) -> tuple | ImageClassifierOutput:
|
| 621 |
+
r"""
|
| 622 |
+
labels (`torch.LongTensor` of shape `(batch_size,)`, *optional*):
|
| 623 |
+
Labels for computing the image classification/regression loss. Indices should be in `[0, ...,
|
| 624 |
+
config.num_labels - 1]`. If `config.num_labels == 1` a regression loss is computed (Mean-Square loss), If
|
| 625 |
+
`config.num_labels > 1` a classification loss is computed (Cross-Entropy).
|
| 626 |
+
|
| 627 |
+
Examples:
|
| 628 |
+
|
| 629 |
+
```python
|
| 630 |
+
>>> import av
|
| 631 |
+
>>> import torch
|
| 632 |
+
>>> import numpy as np
|
| 633 |
+
|
| 634 |
+
>>> from transformers import AutoImageProcessor, TimesformerForVideoClassification
|
| 635 |
+
>>> from huggingface_hub import hf_hub_download
|
| 636 |
+
|
| 637 |
+
>>> np.random.seed(0)
|
| 638 |
+
|
| 639 |
+
|
| 640 |
+
>>> def read_video_pyav(container, indices):
|
| 641 |
+
... '''
|
| 642 |
+
... Decode the video with PyAV decoder.
|
| 643 |
+
... Args:
|
| 644 |
+
... container (`av.container.input.InputContainer`): PyAV container.
|
| 645 |
+
... indices (`list[int]`): List of frame indices to decode.
|
| 646 |
+
... Returns:
|
| 647 |
+
... result (np.ndarray): np array of decoded frames of shape (num_frames, height, width, 3).
|
| 648 |
+
... '''
|
| 649 |
+
... frames = []
|
| 650 |
+
... container.seek(0)
|
| 651 |
+
... start_index = indices[0]
|
| 652 |
+
... end_index = indices[-1]
|
| 653 |
+
... for i, frame in enumerate(container.decode(video=0)):
|
| 654 |
+
... if i > end_index:
|
| 655 |
+
... break
|
| 656 |
+
... if i >= start_index and i in indices:
|
| 657 |
+
... frames.append(frame)
|
| 658 |
+
... return np.stack([x.to_ndarray(format="rgb24") for x in frames])
|
| 659 |
+
|
| 660 |
+
|
| 661 |
+
>>> def sample_frame_indices(clip_len, frame_sample_rate, seg_len):
|
| 662 |
+
... '''
|
| 663 |
+
... Sample a given number of frame indices from the video.
|
| 664 |
+
... Args:
|
| 665 |
+
... clip_len (`int`): Total number of frames to sample.
|
| 666 |
+
... frame_sample_rate (`int`): Sample every n-th frame.
|
| 667 |
+
... seg_len (`int`): Maximum allowed index of sample's last frame.
|
| 668 |
+
... Returns:
|
| 669 |
+
... indices (`list[int]`): List of sampled frame indices
|
| 670 |
+
... '''
|
| 671 |
+
... converted_len = int(clip_len * frame_sample_rate)
|
| 672 |
+
... end_idx = np.random.randint(converted_len, seg_len)
|
| 673 |
+
... start_idx = end_idx - converted_len
|
| 674 |
+
... indices = np.linspace(start_idx, end_idx, num=clip_len)
|
| 675 |
+
... indices = np.clip(indices, start_idx, end_idx - 1).astype(np.int64)
|
| 676 |
+
... return indices
|
| 677 |
+
|
| 678 |
+
|
| 679 |
+
>>> # video clip consists of 300 frames (10 seconds at 30 FPS)
|
| 680 |
+
>>> file_path = hf_hub_download(
|
| 681 |
+
... repo_id="nielsr/video-demo", filename="eating_spaghetti.mp4", repo_type="dataset"
|
| 682 |
+
... )
|
| 683 |
+
>>> container = av.open(file_path)
|
| 684 |
+
|
| 685 |
+
>>> # sample 8 frames
|
| 686 |
+
>>> indices = sample_frame_indices(clip_len=8, frame_sample_rate=1, seg_len=container.streams.video[0].frames)
|
| 687 |
+
>>> video = read_video_pyav(container, indices)
|
| 688 |
+
|
| 689 |
+
>>> image_processor = AutoImageProcessor.from_pretrained("MCG-NJU/videomae-base-finetuned-kinetics")
|
| 690 |
+
>>> model = TimesformerForVideoClassification.from_pretrained("facebook/timesformer-base-finetuned-k400")
|
| 691 |
+
|
| 692 |
+
>>> inputs = image_processor(list(video), return_tensors="pt")
|
| 693 |
+
|
| 694 |
+
>>> with torch.no_grad():
|
| 695 |
+
... outputs = model(**inputs)
|
| 696 |
+
... logits = outputs.logits
|
| 697 |
+
|
| 698 |
+
>>> # model predicts one of the 400 Kinetics-400 classes
|
| 699 |
+
>>> predicted_label = logits.argmax(-1).item()
|
| 700 |
+
>>> print(model.config.id2label[predicted_label])
|
| 701 |
+
eating spaghetti
|
| 702 |
+
```"""
|
| 703 |
+
return_dict = return_dict if return_dict is not None else self.config.return_dict
|
| 704 |
+
|
| 705 |
+
outputs = self.timesformer(
|
| 706 |
+
pixel_values,
|
| 707 |
+
output_attentions=output_attentions,
|
| 708 |
+
output_hidden_states=output_hidden_states,
|
| 709 |
+
return_dict=return_dict,
|
| 710 |
+
)
|
| 711 |
+
|
| 712 |
+
sequence_output = outputs[0][:, 0]
|
| 713 |
+
|
| 714 |
+
logits = self.classifier(sequence_output)
|
| 715 |
+
|
| 716 |
+
loss = None
|
| 717 |
+
if labels is not None:
|
| 718 |
+
if self.config.problem_type is None:
|
| 719 |
+
if self.num_labels == 1:
|
| 720 |
+
self.config.problem_type = "regression"
|
| 721 |
+
elif self.num_labels > 1 and (labels.dtype == torch.long or labels.dtype == torch.int):
|
| 722 |
+
self.config.problem_type = "single_label_classification"
|
| 723 |
+
else:
|
| 724 |
+
self.config.problem_type = "multi_label_classification"
|
| 725 |
+
|
| 726 |
+
if self.config.problem_type == "regression":
|
| 727 |
+
loss_fct = MSELoss()
|
| 728 |
+
if self.num_labels == 1:
|
| 729 |
+
loss = loss_fct(logits.squeeze(), labels.squeeze())
|
| 730 |
+
else:
|
| 731 |
+
loss = loss_fct(logits, labels)
|
| 732 |
+
elif self.config.problem_type == "single_label_classification":
|
| 733 |
+
loss_fct = CrossEntropyLoss()
|
| 734 |
+
loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))
|
| 735 |
+
elif self.config.problem_type == "multi_label_classification":
|
| 736 |
+
loss_fct = BCEWithLogitsLoss()
|
| 737 |
+
loss = loss_fct(logits, labels)
|
| 738 |
+
|
| 739 |
+
if not return_dict:
|
| 740 |
+
output = (logits,) + outputs[1:]
|
| 741 |
+
return ((loss,) + output) if loss is not None else output
|
| 742 |
+
|
| 743 |
+
return ImageClassifierOutput(
|
| 744 |
+
loss=loss,
|
| 745 |
+
logits=logits,
|
| 746 |
+
hidden_states=outputs.hidden_states,
|
| 747 |
+
attentions=outputs.attentions,
|
| 748 |
+
)
|
| 749 |
+
|
| 750 |
+
|
| 751 |
+
__all__ = ["TimesformerModel", "TimesformerForVideoClassification", "TimesformerPreTrainedModel"]
|