omdev 0.0.0.dev162__tar.gz → 0.0.0.dev164__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of omdev might be problematic. Click here for more details.
- {omdev-0.0.0.dev162/omdev.egg-info → omdev-0.0.0.dev164}/PKG-INFO +2 -2
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/amalg/__main__.py +1 -1
- omdev-0.0.0.dev164/omdev/amalg/gen.py +212 -0
- omdev-0.0.0.dev164/omdev/amalg/imports.py +98 -0
- omdev-0.0.0.dev164/omdev/amalg/main.py +154 -0
- omdev-0.0.0.dev164/omdev/amalg/manifests.py +49 -0
- omdev-0.0.0.dev164/omdev/amalg/resources.py +99 -0
- omdev-0.0.0.dev164/omdev/amalg/srcfiles.py +120 -0
- omdev-0.0.0.dev164/omdev/amalg/strip.py +70 -0
- omdev-0.0.0.dev164/omdev/amalg/types.py +6 -0
- omdev-0.0.0.dev164/omdev/amalg/typing.py +106 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/manifests/build.py +2 -3
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/manifests.py +2 -3
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev.egg-info/SOURCES.txt +9 -1
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/pyproject.toml +2 -2
- omdev-0.0.0.dev162/omdev/amalg/amalg.py +0 -782
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/LICENSE +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/README.rst +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/.manifests.json +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/classdot.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/main.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/clipboard/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/clipboard/clipboard.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/clipboard/darwin_cf.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/clipboard/linux_x11.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/git/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/git/revisions.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/git/status.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/git/subtrees.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/providers.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/pyenv.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/standalone.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/system.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/manifests/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/manifests/main.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pip.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/ptk/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/ptk/apps/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/ptk/apps/ncdu.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pycharm/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pycharm/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pycharm/cli.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/pyproject/venvs.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/revisions.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/execrss.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/exectime.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/secrets.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tokens.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/toml/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/toml/parser.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/toml/writer.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/cloc.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/doc.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/git.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/importscan.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/cli.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/formats.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/io.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/parsing.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/processing.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/json/rendering.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev/wheelfile.py +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev162 → omdev-0.0.0.dev164}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev164
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: >=3.12
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
|
15
|
+
Requires-Dist: omlish==0.0.0.dev164
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: black~=24.10; extra == "all"
|
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import os.path
|
|
3
|
+
import textwrap
|
|
4
|
+
import typing as ta
|
|
5
|
+
|
|
6
|
+
from omlish import cached
|
|
7
|
+
from omlish import collections as col
|
|
8
|
+
from omlish import lang
|
|
9
|
+
from omlish.lite.runtime import LITE_REQUIRED_PYTHON_VERSION
|
|
10
|
+
|
|
11
|
+
from .. import tokens as tks
|
|
12
|
+
from .srcfiles import SrcFile
|
|
13
|
+
from .srcfiles import make_src_file
|
|
14
|
+
from .strip import strip_main_lines
|
|
15
|
+
from .types import Tokens
|
|
16
|
+
from .typing import Typing
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
##
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
SECTION_SEP = '#' * 40 + '\n'
|
|
23
|
+
|
|
24
|
+
RUFF_DISABLES: ta.AbstractSet[str] = {
|
|
25
|
+
'UP006', # non-pep585-annotation
|
|
26
|
+
'UP007', # non-pep604-annotation
|
|
27
|
+
'UP036', # outdated-version-block
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
OUTPUT_COMMENT = '# @omlish-amalg-output '
|
|
31
|
+
SCAN_COMMENT = '# @omlish-amalg '
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AmalgGenerator:
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
main_path: str,
|
|
38
|
+
*,
|
|
39
|
+
mounts: ta.Mapping[str, str],
|
|
40
|
+
output_dir: str | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
super().__init__()
|
|
43
|
+
|
|
44
|
+
self._main_path = main_path
|
|
45
|
+
self._mounts = mounts
|
|
46
|
+
self._output_dir = output_dir
|
|
47
|
+
|
|
48
|
+
@cached.function
|
|
49
|
+
def _src_files(self) -> dict[str, SrcFile]:
|
|
50
|
+
src_files: dict[str, SrcFile] = {}
|
|
51
|
+
todo = [self._main_path]
|
|
52
|
+
while todo:
|
|
53
|
+
src_path = todo.pop()
|
|
54
|
+
if src_path in src_files:
|
|
55
|
+
continue
|
|
56
|
+
|
|
57
|
+
f = make_src_file(
|
|
58
|
+
src_path,
|
|
59
|
+
mounts=self._mounts,
|
|
60
|
+
)
|
|
61
|
+
src_files[src_path] = f
|
|
62
|
+
|
|
63
|
+
for imp in f.imports:
|
|
64
|
+
if (mp := imp.mod_path) is not None:
|
|
65
|
+
todo.append(mp)
|
|
66
|
+
|
|
67
|
+
return src_files
|
|
68
|
+
|
|
69
|
+
@cached.function
|
|
70
|
+
def _main_file(self) -> SrcFile:
|
|
71
|
+
return self._src_files()[self._main_path]
|
|
72
|
+
|
|
73
|
+
@cached.function
|
|
74
|
+
def _header_lines(self) -> list[Tokens]:
|
|
75
|
+
header_lines = []
|
|
76
|
+
|
|
77
|
+
if self._main_file().header_lines:
|
|
78
|
+
header_lines.extend([
|
|
79
|
+
hl
|
|
80
|
+
for hlts in self._main_file().header_lines
|
|
81
|
+
if not (hl := tks.join_toks(hlts)).startswith(SCAN_COMMENT)
|
|
82
|
+
])
|
|
83
|
+
|
|
84
|
+
if self._output_dir is not None:
|
|
85
|
+
ogf = os.path.relpath(self._main_path, self._output_dir)
|
|
86
|
+
else:
|
|
87
|
+
ogf = os.path.basename(self._main_path)
|
|
88
|
+
|
|
89
|
+
additional_header_lines = [
|
|
90
|
+
'#!/usr/bin/env python3\n',
|
|
91
|
+
'# noinspection DuplicatedCode\n',
|
|
92
|
+
'# @omlish-lite\n',
|
|
93
|
+
'# @omlish-script\n',
|
|
94
|
+
f'{OUTPUT_COMMENT.strip()} {ogf}\n',
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
ruff_disables = sorted({
|
|
98
|
+
*lang.flatten(f.ruff_noqa for f in self._src_files().values()),
|
|
99
|
+
*RUFF_DISABLES,
|
|
100
|
+
})
|
|
101
|
+
if ruff_disables:
|
|
102
|
+
additional_header_lines.append(f'# ruff: noqa: {" ".join(sorted(ruff_disables))}\n')
|
|
103
|
+
|
|
104
|
+
return [*additional_header_lines, *header_lines]
|
|
105
|
+
|
|
106
|
+
@cached.function
|
|
107
|
+
def gen_amalg(self) -> str:
|
|
108
|
+
src_files = self._src_files()
|
|
109
|
+
|
|
110
|
+
##
|
|
111
|
+
|
|
112
|
+
out = io.StringIO()
|
|
113
|
+
|
|
114
|
+
##
|
|
115
|
+
|
|
116
|
+
out.write(''.join(self._header_lines()))
|
|
117
|
+
|
|
118
|
+
##
|
|
119
|
+
|
|
120
|
+
all_imps = [i for f in src_files.values() for i in f.imports]
|
|
121
|
+
gl_imps = [i for i in all_imps if i.mod_path is None]
|
|
122
|
+
|
|
123
|
+
dct: dict = {
|
|
124
|
+
('sys', None, None): ['import sys\n'],
|
|
125
|
+
}
|
|
126
|
+
if any(sf.has_binary_resources for sf in src_files.values()):
|
|
127
|
+
dct[('base64', None, None)] = ['import base64\n']
|
|
128
|
+
for imp in gl_imps:
|
|
129
|
+
dct.setdefault((imp.mod, imp.item, imp.as_), []).append(imp)
|
|
130
|
+
for _, l in sorted(dct.items()):
|
|
131
|
+
il = l[0]
|
|
132
|
+
out.write(il if isinstance(il, str) else tks.join_toks(il.toks))
|
|
133
|
+
if dct:
|
|
134
|
+
out.write('\n\n')
|
|
135
|
+
|
|
136
|
+
##
|
|
137
|
+
|
|
138
|
+
out.write(SECTION_SEP)
|
|
139
|
+
out.write('\n\n')
|
|
140
|
+
|
|
141
|
+
version_check_fail_msg = (
|
|
142
|
+
f'Requires python {LITE_REQUIRED_PYTHON_VERSION!r}, '
|
|
143
|
+
f'got {{sys.version_info}} from {{sys.executable}}'
|
|
144
|
+
)
|
|
145
|
+
out.write(textwrap.dedent(f"""
|
|
146
|
+
if sys.version_info < {LITE_REQUIRED_PYTHON_VERSION!r}:
|
|
147
|
+
raise OSError(f{version_check_fail_msg!r}) # noqa
|
|
148
|
+
""").lstrip())
|
|
149
|
+
out.write('\n\n')
|
|
150
|
+
|
|
151
|
+
##
|
|
152
|
+
|
|
153
|
+
ts = list(col.toposort({ # noqa
|
|
154
|
+
f.path: {mp for i in f.imports if (mp := i.mod_path) is not None}
|
|
155
|
+
for f in src_files.values()
|
|
156
|
+
}))
|
|
157
|
+
sfs = [sf for ss in ts for sf in sorted(ss)]
|
|
158
|
+
|
|
159
|
+
##
|
|
160
|
+
|
|
161
|
+
tyd: dict[str, list[Typing]] = {}
|
|
162
|
+
tys = set()
|
|
163
|
+
for sf in sfs:
|
|
164
|
+
f = src_files[sf]
|
|
165
|
+
for ty in f.typings:
|
|
166
|
+
if ty.src not in tys:
|
|
167
|
+
tyd.setdefault(f.path, []).append(ty)
|
|
168
|
+
tys.add(ty.src)
|
|
169
|
+
if tys:
|
|
170
|
+
out.write(SECTION_SEP)
|
|
171
|
+
out.write('\n\n')
|
|
172
|
+
for i, (sf, ftys) in enumerate(tyd.items()):
|
|
173
|
+
f = src_files[sf]
|
|
174
|
+
if i:
|
|
175
|
+
out.write('\n')
|
|
176
|
+
if f is not self._main_file():
|
|
177
|
+
rp = os.path.relpath(f.path, os.path.dirname(self._main_file().path))
|
|
178
|
+
else:
|
|
179
|
+
rp = os.path.basename(f.path)
|
|
180
|
+
out.write(f'# {rp}\n')
|
|
181
|
+
for ty in ftys:
|
|
182
|
+
out.write(ty.src)
|
|
183
|
+
if tys:
|
|
184
|
+
out.write('\n\n')
|
|
185
|
+
|
|
186
|
+
##
|
|
187
|
+
|
|
188
|
+
main_file = self._main_file()
|
|
189
|
+
for i, sf in enumerate(sfs):
|
|
190
|
+
f = src_files[sf]
|
|
191
|
+
out.write(SECTION_SEP)
|
|
192
|
+
if f is not main_file:
|
|
193
|
+
rp = os.path.relpath(f.path, main_file.path)
|
|
194
|
+
else:
|
|
195
|
+
rp = os.path.basename(f.path)
|
|
196
|
+
out.write(f'# {rp}\n')
|
|
197
|
+
if f is not main_file and f.header_lines:
|
|
198
|
+
out.write(tks.join_lines(f.header_lines))
|
|
199
|
+
out.write(f'\n\n')
|
|
200
|
+
cls = f.content_lines
|
|
201
|
+
if f is not main_file:
|
|
202
|
+
cls = strip_main_lines(cls)
|
|
203
|
+
sf_src = tks.join_lines(cls)
|
|
204
|
+
out.write(sf_src.strip())
|
|
205
|
+
if i < len(sfs) - 1:
|
|
206
|
+
out.write('\n\n\n')
|
|
207
|
+
else:
|
|
208
|
+
out.write('\n')
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
|
|
212
|
+
return out.getvalue()
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import dataclasses as dc
|
|
2
|
+
import os.path
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
from omlish import check
|
|
6
|
+
|
|
7
|
+
from .. import tokens as tks
|
|
8
|
+
from .types import Tokens
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
|
15
|
+
class Import:
|
|
16
|
+
mod: str
|
|
17
|
+
item: str | None
|
|
18
|
+
as_: str | None
|
|
19
|
+
|
|
20
|
+
src_path: str
|
|
21
|
+
line: int
|
|
22
|
+
|
|
23
|
+
mod_path: str | None
|
|
24
|
+
|
|
25
|
+
toks: Tokens = dc.field(repr=False)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def make_import(
|
|
29
|
+
lts: Tokens,
|
|
30
|
+
*,
|
|
31
|
+
src_path: str,
|
|
32
|
+
mounts: ta.Mapping[str, str],
|
|
33
|
+
) -> Import | None:
|
|
34
|
+
if not lts:
|
|
35
|
+
return None
|
|
36
|
+
ft = lts[0]
|
|
37
|
+
|
|
38
|
+
if ft.name != 'NAME' or ft.src not in ('import', 'from'):
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
ml = []
|
|
42
|
+
il: list[str] | None = None
|
|
43
|
+
as_ = None
|
|
44
|
+
for tok in (it := iter(tks.ignore_ws(lts[1:]))):
|
|
45
|
+
if tok.name in ('NAME', 'OP'):
|
|
46
|
+
if tok.src == 'as':
|
|
47
|
+
check.none(as_)
|
|
48
|
+
nt = next(it)
|
|
49
|
+
check.equal(nt.name, 'NAME')
|
|
50
|
+
as_ = nt.src
|
|
51
|
+
elif tok.src == 'import':
|
|
52
|
+
check.equal(ft.src, 'from')
|
|
53
|
+
il = []
|
|
54
|
+
elif il is not None:
|
|
55
|
+
il.append(tok.src)
|
|
56
|
+
else:
|
|
57
|
+
ml.append(tok.src)
|
|
58
|
+
else:
|
|
59
|
+
raise Exception(tok)
|
|
60
|
+
|
|
61
|
+
mod = ''.join(ml)
|
|
62
|
+
item = ''.join(il) if il is not None else None
|
|
63
|
+
|
|
64
|
+
if (mnt := mounts.get(mod.partition('.')[0])) is not None:
|
|
65
|
+
ps = mod.split('.')
|
|
66
|
+
mod_path = os.path.abspath(os.path.join(
|
|
67
|
+
mnt,
|
|
68
|
+
*ps[1:-1],
|
|
69
|
+
ps[-1] + '.py',
|
|
70
|
+
))
|
|
71
|
+
|
|
72
|
+
elif not mod.startswith('.'):
|
|
73
|
+
mod_path = None
|
|
74
|
+
|
|
75
|
+
else:
|
|
76
|
+
parts = mod.split('.')
|
|
77
|
+
nd = len(parts) - parts[::-1].index('')
|
|
78
|
+
mod_path = os.path.abspath(os.path.join(
|
|
79
|
+
os.path.dirname(src_path),
|
|
80
|
+
'../' * (nd - 1),
|
|
81
|
+
*parts[nd:-1],
|
|
82
|
+
parts[-1] + '.py',
|
|
83
|
+
))
|
|
84
|
+
|
|
85
|
+
mod = check.isinstance(mod_path, str)
|
|
86
|
+
|
|
87
|
+
return Import(
|
|
88
|
+
mod=mod,
|
|
89
|
+
item=item,
|
|
90
|
+
as_=as_,
|
|
91
|
+
|
|
92
|
+
src_path=src_path,
|
|
93
|
+
line=ft.line,
|
|
94
|
+
|
|
95
|
+
mod_path=mod_path,
|
|
96
|
+
|
|
97
|
+
toks=lts,
|
|
98
|
+
)
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Conventions:
|
|
3
|
+
- must import whole global modules, if aliased must all match
|
|
4
|
+
- must import 'from' items for local modules
|
|
5
|
+
|
|
6
|
+
TODO:
|
|
7
|
+
- !! check only importing lite code
|
|
8
|
+
- !! strip manifests? or relegate them to a separate tiny module ala __main__.py?
|
|
9
|
+
- # @omlish-no-amalg ? in cli.types? will strip stmt (more than 1 line) following @manifest, so shouldn't import
|
|
10
|
+
- more sanity checks lol
|
|
11
|
+
- typealias - support # noqa, other comments, and lamely support multiline by just stealing lines till it parses
|
|
12
|
+
- remove `if __name__ == '__main__':` blocks - thus, convention: no def _main() for these
|
|
13
|
+
|
|
14
|
+
See:
|
|
15
|
+
- https://github.com/xonsh/amalgamate - mine is for portability not speed, and doesn't try to work on unmodified code
|
|
16
|
+
|
|
17
|
+
Targets:
|
|
18
|
+
- interp
|
|
19
|
+
- pyproject
|
|
20
|
+
- precheck
|
|
21
|
+
- build
|
|
22
|
+
- pyremote
|
|
23
|
+
- bootstrap
|
|
24
|
+
- deploy
|
|
25
|
+
- supervisor?
|
|
26
|
+
"""
|
|
27
|
+
import argparse
|
|
28
|
+
import logging
|
|
29
|
+
import os.path
|
|
30
|
+
import typing as ta
|
|
31
|
+
|
|
32
|
+
from omlish import check
|
|
33
|
+
from omlish.logs import all as logs
|
|
34
|
+
|
|
35
|
+
from .gen import SCAN_COMMENT
|
|
36
|
+
from .gen import AmalgGenerator
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
log = logging.getLogger(__name__)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _gen_one(
|
|
46
|
+
input_path: str,
|
|
47
|
+
output_path: str | None,
|
|
48
|
+
*,
|
|
49
|
+
mounts: ta.Mapping[str, str],
|
|
50
|
+
) -> None:
|
|
51
|
+
log.info('Generating: %s -> %s', input_path, output_path)
|
|
52
|
+
|
|
53
|
+
src = AmalgGenerator(
|
|
54
|
+
input_path,
|
|
55
|
+
mounts=mounts,
|
|
56
|
+
output_dir=os.path.dirname(output_path if output_path is not None else input_path),
|
|
57
|
+
).gen_amalg()
|
|
58
|
+
|
|
59
|
+
if output_path is not None:
|
|
60
|
+
with open(output_path, 'w') as f:
|
|
61
|
+
f.write(src)
|
|
62
|
+
os.chmod(output_path, os.stat(input_path).st_mode)
|
|
63
|
+
|
|
64
|
+
else:
|
|
65
|
+
print(src)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _scan_one(
|
|
69
|
+
input_path: str,
|
|
70
|
+
**kwargs: ta.Any,
|
|
71
|
+
) -> None:
|
|
72
|
+
if not input_path.endswith('.py'):
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
with open(input_path) as f:
|
|
76
|
+
src = f.read()
|
|
77
|
+
|
|
78
|
+
sls = [l for l in src.splitlines() if l.startswith(SCAN_COMMENT)]
|
|
79
|
+
for sl in sls:
|
|
80
|
+
sas = sl[len(SCAN_COMMENT):].split()
|
|
81
|
+
if len(sas) != 1:
|
|
82
|
+
raise Exception(f'Invalid scan args: {input_path=} {sas=}')
|
|
83
|
+
|
|
84
|
+
output_path = os.path.abspath(os.path.join(os.path.dirname(input_path), sas[0]))
|
|
85
|
+
_gen_one(
|
|
86
|
+
input_path,
|
|
87
|
+
output_path,
|
|
88
|
+
**kwargs,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _gen_cmd(args) -> None:
|
|
93
|
+
if not os.path.isfile('pyproject.toml'):
|
|
94
|
+
raise Exception('Not in project root')
|
|
95
|
+
|
|
96
|
+
mounts = {}
|
|
97
|
+
for m in args.mounts or ():
|
|
98
|
+
if ':' not in m:
|
|
99
|
+
mounts[m] = os.path.abspath(m)
|
|
100
|
+
else:
|
|
101
|
+
k, v = m.split(':')
|
|
102
|
+
mounts[k] = os.path.abspath(v)
|
|
103
|
+
|
|
104
|
+
for i in args.inputs:
|
|
105
|
+
if os.path.isdir(i):
|
|
106
|
+
log.info('Scanning %s', i)
|
|
107
|
+
for we_dirpath, we_dirnames, we_filenames in os.walk(i): # noqa
|
|
108
|
+
for fname in we_filenames:
|
|
109
|
+
_scan_one(
|
|
110
|
+
os.path.abspath(os.path.join(we_dirpath, fname)),
|
|
111
|
+
mounts=mounts,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
else:
|
|
115
|
+
output_dir = args.output
|
|
116
|
+
if output_dir is not None:
|
|
117
|
+
output_path = check.isinstance(os.path.join(output_dir, os.path.basename(i)), str)
|
|
118
|
+
else:
|
|
119
|
+
output_path = None
|
|
120
|
+
|
|
121
|
+
_gen_one(
|
|
122
|
+
os.path.abspath(i),
|
|
123
|
+
output_path,
|
|
124
|
+
mounts=mounts,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
129
|
+
parser = argparse.ArgumentParser()
|
|
130
|
+
|
|
131
|
+
subparsers = parser.add_subparsers()
|
|
132
|
+
|
|
133
|
+
parser_gen = subparsers.add_parser('gen')
|
|
134
|
+
parser_gen.add_argument('--mount', '-m', dest='mounts', action='append')
|
|
135
|
+
parser_gen.add_argument('--output', '-o')
|
|
136
|
+
parser_gen.add_argument('inputs', nargs='+')
|
|
137
|
+
parser_gen.set_defaults(func=_gen_cmd)
|
|
138
|
+
|
|
139
|
+
return parser
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _main() -> None:
|
|
143
|
+
logs.configure_standard_logging('INFO')
|
|
144
|
+
|
|
145
|
+
parser = _build_parser()
|
|
146
|
+
args = parser.parse_args()
|
|
147
|
+
if not getattr(args, 'func', None):
|
|
148
|
+
parser.print_help()
|
|
149
|
+
else:
|
|
150
|
+
args.func(args)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == '__main__':
|
|
154
|
+
_main()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
|
|
3
|
+
import tokenize_rt as trt
|
|
4
|
+
|
|
5
|
+
from omlish import check
|
|
6
|
+
|
|
7
|
+
from .. import tokens as tks
|
|
8
|
+
from .types import Tokens
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def is_manifest_comment(line: Tokens) -> bool:
|
|
15
|
+
if not line:
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
(ft := line[0]).name == 'COMMENT' and
|
|
20
|
+
ft.src.startswith('# @omlish-manifest')
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def comment_out_manifest_comment(
|
|
25
|
+
line: Tokens,
|
|
26
|
+
cls: list[Tokens],
|
|
27
|
+
i: int,
|
|
28
|
+
) -> tuple[list[Tokens], int]:
|
|
29
|
+
mls = [line]
|
|
30
|
+
while True:
|
|
31
|
+
mls.append(cls[i])
|
|
32
|
+
i += 1
|
|
33
|
+
|
|
34
|
+
msrc = tks.join_lines(mls).strip()
|
|
35
|
+
try:
|
|
36
|
+
node = ast.parse(msrc)
|
|
37
|
+
except SyntaxError:
|
|
38
|
+
continue
|
|
39
|
+
|
|
40
|
+
mmod = check.isinstance(node, ast.Module)
|
|
41
|
+
check.isinstance(check.single(mmod.body), ast.Assign)
|
|
42
|
+
break
|
|
43
|
+
|
|
44
|
+
out: list[Tokens] = [
|
|
45
|
+
[trt.Token('COMMENT', '# ' + tks.join_toks(ml))]
|
|
46
|
+
for ml in mls
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
return out, i
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import base64
|
|
3
|
+
import itertools
|
|
4
|
+
import os.path
|
|
5
|
+
import typing as ta
|
|
6
|
+
|
|
7
|
+
import tokenize_rt as trt
|
|
8
|
+
|
|
9
|
+
from .. import tokens as tks
|
|
10
|
+
from .types import Tokens
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
##
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RootLevelResourcesRead(ta.NamedTuple):
|
|
17
|
+
variable: str
|
|
18
|
+
kind: ta.Literal['binary', 'text']
|
|
19
|
+
resource: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def is_root_level_resources_read(lts: Tokens) -> RootLevelResourcesRead | None:
|
|
23
|
+
wts = list(tks.ignore_ws(lts, keep=['INDENT']))
|
|
24
|
+
|
|
25
|
+
if not tks.match_toks(wts, [
|
|
26
|
+
('NAME', None),
|
|
27
|
+
('OP', '='),
|
|
28
|
+
('NAME', ('read_package_resource_binary', 'read_package_resource_text')),
|
|
29
|
+
('OP', '('),
|
|
30
|
+
('NAME', '__package__'),
|
|
31
|
+
('OP', ','),
|
|
32
|
+
('STRING', None),
|
|
33
|
+
('OP', ')'),
|
|
34
|
+
]):
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
return RootLevelResourcesRead(
|
|
38
|
+
wts[0].src,
|
|
39
|
+
'binary' if wts[2].src == 'read_package_resource_binary' else 'text',
|
|
40
|
+
ast.literal_eval(wts[6].src),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
##
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def build_resource_lines(
|
|
48
|
+
rsrc: RootLevelResourcesRead,
|
|
49
|
+
path: str,
|
|
50
|
+
) -> list[Tokens]:
|
|
51
|
+
rf = os.path.join(os.path.dirname(path), rsrc.resource)
|
|
52
|
+
|
|
53
|
+
if rsrc.kind == 'binary':
|
|
54
|
+
with open(rf, 'rb') as bf:
|
|
55
|
+
rb = bf.read() # noqa
|
|
56
|
+
|
|
57
|
+
out: list[Tokens] = [[
|
|
58
|
+
trt.Token(name='NAME', src=rsrc.variable),
|
|
59
|
+
trt.Token(name='UNIMPORTANT_WS', src=' '),
|
|
60
|
+
trt.Token(name='OP', src='='),
|
|
61
|
+
trt.Token(name='UNIMPORTANT_WS', src=' '),
|
|
62
|
+
trt.Token(name='NAME', src='base64'),
|
|
63
|
+
trt.Token(name='OP', src='.'),
|
|
64
|
+
trt.Token(name='NAME', src='b64decode'),
|
|
65
|
+
trt.Token(name='OP', src='('),
|
|
66
|
+
trt.Token(name='NL', src='\n'),
|
|
67
|
+
]]
|
|
68
|
+
|
|
69
|
+
rb64 = base64.b64encode(rb).decode('ascii')
|
|
70
|
+
for chunk in itertools.batched(rb64, 96):
|
|
71
|
+
out.append([
|
|
72
|
+
trt.Token(name='UNIMPORTANT_WS', src=' '),
|
|
73
|
+
trt.Token(name='STRING', src=f"'{''.join(chunk)}'"),
|
|
74
|
+
trt.Token(name='NL', src='\n'),
|
|
75
|
+
])
|
|
76
|
+
|
|
77
|
+
out.append([
|
|
78
|
+
trt.Token(name='OP', src=')'),
|
|
79
|
+
trt.Token(name='NEWLINE', src='\n'),
|
|
80
|
+
])
|
|
81
|
+
|
|
82
|
+
return out
|
|
83
|
+
|
|
84
|
+
elif rsrc.kind == 'text':
|
|
85
|
+
with open(rf) as tf:
|
|
86
|
+
rt = tf.read() # noqa
|
|
87
|
+
rt = rt.replace('\\', '\\\\') # Escape backslashes
|
|
88
|
+
rt = rt.replace('"""', r'\"\"\"')
|
|
89
|
+
return [[
|
|
90
|
+
trt.Token(name='NAME', src=rsrc.variable),
|
|
91
|
+
trt.Token(name='UNIMPORTANT_WS', src=' '),
|
|
92
|
+
trt.Token(name='OP', src='='),
|
|
93
|
+
trt.Token(name='UNIMPORTANT_WS', src=' '),
|
|
94
|
+
trt.Token(name='STRING', src=f'"""\\\n{rt}"""\n'),
|
|
95
|
+
trt.Token(name='NEWLINE', src=''),
|
|
96
|
+
]]
|
|
97
|
+
|
|
98
|
+
else:
|
|
99
|
+
raise ValueError(rsrc.kind)
|