omlish 0.0.0.dev447__py3-none-any.whl → 0.0.0.dev484__py3-none-any.whl
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 omlish might be problematic. Click here for more details.
- omlish/.omlish-manifests.json +12 -0
- omlish/__about__.py +15 -15
- omlish/argparse/all.py +17 -9
- omlish/argparse/cli.py +16 -3
- omlish/argparse/utils.py +21 -0
- omlish/asyncs/asyncio/rlock.py +110 -0
- omlish/asyncs/asyncio/sync.py +43 -0
- omlish/asyncs/asyncio/utils.py +2 -0
- omlish/asyncs/sync.py +25 -0
- omlish/bootstrap/_marshal.py +1 -1
- omlish/bootstrap/diag.py +12 -21
- omlish/bootstrap/main.py +2 -5
- omlish/bootstrap/sys.py +27 -28
- omlish/cexts/__init__.py +0 -0
- omlish/cexts/include/omlish/omlish.hh +1 -0
- omlish/collections/__init__.py +13 -1
- omlish/collections/attrregistry.py +210 -0
- omlish/collections/cache/impl.py +1 -0
- omlish/collections/identity.py +1 -0
- omlish/collections/mappings.py +28 -0
- omlish/collections/trie.py +5 -1
- omlish/collections/utils.py +77 -0
- omlish/concurrent/all.py +2 -1
- omlish/concurrent/futures.py +25 -0
- omlish/concurrent/threadlets.py +1 -1
- omlish/daemons/reparent.py +2 -3
- omlish/daemons/spawning.py +2 -3
- omlish/dataclasses/__init__.py +2 -0
- omlish/dataclasses/impl/api/classes/decorator.py +3 -0
- omlish/dataclasses/impl/api/classes/make.py +3 -0
- omlish/dataclasses/impl/concerns/repr.py +15 -2
- omlish/dataclasses/impl/configs.py +97 -37
- omlish/dataclasses/impl/generation/compilation.py +21 -19
- omlish/dataclasses/impl/generation/globals.py +1 -0
- omlish/dataclasses/impl/generation/ops.py +1 -0
- omlish/dataclasses/impl/generation/processor.py +105 -24
- omlish/dataclasses/impl/processing/base.py +8 -0
- omlish/dataclasses/impl/processing/driving.py +8 -8
- omlish/dataclasses/specs.py +1 -0
- omlish/dataclasses/tools/modifiers.py +5 -0
- omlish/diag/cmds/__init__.py +0 -0
- omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
- omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
- omlish/diag/{ps.py → cmds/ps.py} +6 -6
- omlish/diag/pycharm.py +16 -2
- omlish/diag/pydevd.py +58 -40
- omlish/diag/replserver/console.py +1 -1
- omlish/dispatch/__init__.py +18 -12
- omlish/dispatch/methods.py +50 -140
- omlish/dom/rendering.py +1 -1
- omlish/formats/dotenv.py +1 -1
- omlish/formats/json/stream/__init__.py +13 -0
- omlish/funcs/guard.py +225 -0
- omlish/graphs/dot/rendering.py +1 -1
- omlish/http/all.py +44 -4
- omlish/http/clients/asyncs.py +33 -27
- omlish/http/clients/base.py +17 -1
- omlish/http/clients/coro/__init__.py +0 -0
- omlish/http/clients/coro/sync.py +171 -0
- omlish/http/clients/default.py +208 -29
- omlish/http/clients/executor.py +56 -0
- omlish/http/clients/httpx.py +72 -11
- omlish/http/clients/middleware.py +181 -0
- omlish/http/clients/sync.py +33 -27
- omlish/http/clients/syncasync.py +49 -0
- omlish/http/clients/urllib.py +6 -3
- omlish/http/coro/client/connection.py +15 -6
- omlish/http/coro/io.py +2 -0
- omlish/http/flasky/__init__.py +40 -0
- omlish/http/flasky/_compat.py +2 -0
- omlish/http/flasky/api.py +82 -0
- omlish/http/flasky/app.py +203 -0
- omlish/http/flasky/cvs.py +59 -0
- omlish/http/flasky/requests.py +20 -0
- omlish/http/flasky/responses.py +23 -0
- omlish/http/flasky/routes.py +23 -0
- omlish/http/flasky/types.py +15 -0
- omlish/http/urls.py +67 -0
- omlish/inject/__init__.py +38 -18
- omlish/inject/_dataclasses.py +4986 -0
- omlish/inject/binder.py +4 -48
- omlish/inject/elements.py +27 -0
- omlish/inject/helpers/__init__.py +0 -0
- omlish/inject/{utils.py → helpers/constfn.py} +3 -3
- omlish/inject/{tags.py → helpers/id.py} +2 -2
- omlish/inject/helpers/multis.py +143 -0
- omlish/inject/helpers/wrappers.py +54 -0
- omlish/inject/impl/elements.py +47 -17
- omlish/inject/impl/injector.py +20 -19
- omlish/inject/impl/inspect.py +10 -1
- omlish/inject/impl/maysync.py +3 -4
- omlish/inject/impl/multis.py +3 -0
- omlish/inject/impl/sync.py +3 -4
- omlish/inject/injector.py +31 -2
- omlish/inject/inspect.py +35 -0
- omlish/inject/maysync.py +2 -4
- omlish/inject/multis.py +8 -0
- omlish/inject/overrides.py +3 -3
- omlish/inject/privates.py +6 -0
- omlish/inject/providers.py +3 -2
- omlish/inject/sync.py +5 -4
- omlish/io/buffers.py +118 -0
- omlish/io/readers.py +29 -0
- omlish/iterators/transforms.py +2 -2
- omlish/lang/__init__.py +178 -97
- omlish/lang/_asyncs.cc +186 -0
- omlish/lang/asyncs.py +17 -0
- omlish/lang/casing.py +11 -0
- omlish/lang/contextmanagers.py +28 -4
- omlish/lang/functions.py +31 -22
- omlish/lang/imports/_capture.cc +11 -9
- omlish/lang/imports/capture.py +363 -170
- omlish/lang/imports/proxy.py +455 -152
- omlish/lang/lazyglobals.py +22 -9
- omlish/lang/params.py +17 -0
- omlish/lang/recursion.py +0 -1
- omlish/lang/sequences.py +124 -0
- omlish/lite/abstract.py +54 -24
- omlish/lite/asyncs.py +2 -2
- omlish/lite/attrops.py +2 -0
- omlish/lite/contextmanagers.py +4 -4
- omlish/lite/dataclasses.py +44 -0
- omlish/lite/maybes.py +8 -0
- omlish/lite/maysync.py +1 -5
- omlish/lite/pycharm.py +1 -1
- omlish/lite/typing.py +6 -0
- omlish/logs/all.py +1 -1
- omlish/logs/utils.py +1 -1
- omlish/manifests/loading.py +2 -1
- omlish/marshal/__init__.py +33 -13
- omlish/marshal/_dataclasses.py +2774 -0
- omlish/marshal/base/configs.py +12 -0
- omlish/marshal/base/contexts.py +36 -21
- omlish/marshal/base/funcs.py +8 -11
- omlish/marshal/base/options.py +8 -0
- omlish/marshal/base/registries.py +146 -44
- omlish/marshal/base/types.py +40 -16
- omlish/marshal/composite/iterables.py +33 -20
- omlish/marshal/composite/literals.py +20 -18
- omlish/marshal/composite/mappings.py +36 -23
- omlish/marshal/composite/maybes.py +29 -19
- omlish/marshal/composite/newtypes.py +16 -16
- omlish/marshal/composite/optionals.py +14 -14
- omlish/marshal/composite/special.py +15 -15
- omlish/marshal/composite/unions/__init__.py +0 -0
- omlish/marshal/composite/unions/literals.py +93 -0
- omlish/marshal/composite/unions/primitives.py +103 -0
- omlish/marshal/factories/invalidate.py +18 -68
- omlish/marshal/factories/method.py +26 -0
- omlish/marshal/factories/moduleimport/factories.py +22 -65
- omlish/marshal/factories/multi.py +13 -25
- omlish/marshal/factories/recursive.py +42 -56
- omlish/marshal/factories/typecache.py +29 -74
- omlish/marshal/factories/typemap.py +42 -43
- omlish/marshal/objects/dataclasses.py +129 -106
- omlish/marshal/objects/marshal.py +18 -14
- omlish/marshal/objects/namedtuples.py +48 -42
- omlish/marshal/objects/unmarshal.py +19 -15
- omlish/marshal/polymorphism/marshal.py +9 -11
- omlish/marshal/polymorphism/metadata.py +16 -5
- omlish/marshal/polymorphism/standard.py +13 -1
- omlish/marshal/polymorphism/unions.py +15 -105
- omlish/marshal/polymorphism/unmarshal.py +9 -10
- omlish/marshal/singular/enums.py +14 -18
- omlish/marshal/standard.py +10 -6
- omlish/marshal/trivial/any.py +1 -1
- omlish/marshal/trivial/forbidden.py +21 -26
- omlish/metadata.py +23 -1
- omlish/os/forkhooks.py +4 -0
- omlish/os/pidfiles/pinning.py +2 -2
- omlish/reflect/types.py +1 -0
- omlish/secrets/marshal.py +1 -1
- omlish/specs/jmespath/__init__.py +12 -3
- omlish/specs/jmespath/_dataclasses.py +2893 -0
- omlish/specs/jmespath/ast.py +1 -1
- omlish/specs/jsonrpc/__init__.py +13 -0
- omlish/specs/jsonrpc/_marshal.py +32 -23
- omlish/specs/jsonrpc/conns.py +10 -7
- omlish/specs/jsonschema/_marshal.py +1 -1
- omlish/specs/jsonschema/keywords/__init__.py +7 -0
- omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
- omlish/specs/openapi/_marshal.py +31 -22
- omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
- omlish/sql/queries/_marshal.py +2 -2
- omlish/sql/queries/rendering.py +1 -1
- omlish/sql/tabledefs/_marshal.py +1 -1
- omlish/subprocesses/base.py +4 -0
- omlish/subprocesses/editor.py +1 -1
- omlish/sync.py +155 -21
- omlish/term/alt.py +60 -0
- omlish/term/confirm.py +8 -8
- omlish/term/pager.py +235 -0
- omlish/term/terminfo.py +935 -0
- omlish/term/termstate.py +67 -0
- omlish/term/vt100/terminal.py +0 -3
- omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
- omlish/testing/pytest/plugins/skips.py +2 -1
- omlish/testing/unittest/main.py +3 -3
- omlish/text/docwrap/__init__.py +3 -0
- omlish/text/docwrap/__main__.py +11 -0
- omlish/text/docwrap/api.py +83 -0
- omlish/text/docwrap/cli.py +86 -0
- omlish/text/docwrap/groups.py +84 -0
- omlish/text/docwrap/lists.py +167 -0
- omlish/text/docwrap/parts.py +146 -0
- omlish/text/docwrap/reflowing.py +106 -0
- omlish/text/docwrap/rendering.py +151 -0
- omlish/text/docwrap/utils.py +11 -0
- omlish/text/docwrap/wrapping.py +59 -0
- omlish/text/filecache.py +2 -2
- omlish/text/lorem.py +6 -0
- omlish/text/parts.py +2 -2
- omlish/text/textwrap.py +51 -0
- omlish/typedvalues/marshal.py +85 -59
- omlish/typedvalues/values.py +2 -1
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/METADATA +29 -28
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/RECORD +222 -171
- omlish/dataclasses/impl/generation/mangling.py +0 -18
- omlish/funcs/match.py +0 -227
- omlish/marshal/factories/match.py +0 -34
- omlish/marshal/factories/simple.py +0 -28
- /omlish/inject/impl/{providers2.py → providersmap.py} +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/top_level.txt +0 -0
omlish/term/pager.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# ruff: noqa: S602 S605
|
|
2
|
+
#
|
|
3
|
+
# Copyright 2000-2008 Michael Hudson-Doyle <micahel@gmail.com>
|
|
4
|
+
# Armin Rigo
|
|
5
|
+
#
|
|
6
|
+
# All Rights Reserved
|
|
7
|
+
#
|
|
8
|
+
#
|
|
9
|
+
# Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted
|
|
10
|
+
# without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and
|
|
11
|
+
# this permission notice appear in supporting documentation.
|
|
12
|
+
#
|
|
13
|
+
# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
|
|
14
|
+
# MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
|
|
15
|
+
# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
17
|
+
#
|
|
18
|
+
# https://github.com/python/cpython/tree/bcced02604f845b2b71d0a1dd95f95366bd7774d/Lib/_pyrepl
|
|
19
|
+
import io
|
|
20
|
+
import os
|
|
21
|
+
import re
|
|
22
|
+
import subprocess
|
|
23
|
+
import sys
|
|
24
|
+
import tempfile
|
|
25
|
+
import termios
|
|
26
|
+
import tty
|
|
27
|
+
import typing as ta
|
|
28
|
+
|
|
29
|
+
from .. import check
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Pager(ta.Protocol):
|
|
36
|
+
def __call__(self, text: str, title: str = '') -> None:
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_pager() -> Pager:
|
|
41
|
+
"""Decide what method to use for paging through text."""
|
|
42
|
+
|
|
43
|
+
if not hasattr(sys.stdin, 'isatty'):
|
|
44
|
+
return plain_pager
|
|
45
|
+
|
|
46
|
+
if not hasattr(sys.stdout, 'isatty'):
|
|
47
|
+
return plain_pager
|
|
48
|
+
|
|
49
|
+
if not sys.stdin.isatty() or not sys.stdout.isatty():
|
|
50
|
+
return plain_pager
|
|
51
|
+
|
|
52
|
+
if sys.platform == 'emscripten':
|
|
53
|
+
return plain_pager
|
|
54
|
+
|
|
55
|
+
use_pager = os.environ.get('MANPAGER') or os.environ.get('PAGER')
|
|
56
|
+
if use_pager:
|
|
57
|
+
if sys.platform == 'win32': # pipes completely broken in Windows
|
|
58
|
+
raise OSError
|
|
59
|
+
|
|
60
|
+
elif os.environ.get('TERM') in ('dumb', 'emacs'):
|
|
61
|
+
return lambda text, title='': pipe_pager(plain(text), use_pager, title)
|
|
62
|
+
|
|
63
|
+
else:
|
|
64
|
+
return lambda text, title='': pipe_pager(text, use_pager, title)
|
|
65
|
+
|
|
66
|
+
if os.environ.get('TERM') in ('dumb', 'emacs'):
|
|
67
|
+
return plain_pager
|
|
68
|
+
|
|
69
|
+
if sys.platform == 'win32':
|
|
70
|
+
return lambda text, title='': tempfile_pager(plain(text), 'more <')
|
|
71
|
+
|
|
72
|
+
if hasattr(os, 'system') and os.system('(pager) 2>/dev/null') == 0:
|
|
73
|
+
return lambda text, title='': pipe_pager(text, 'pager', title)
|
|
74
|
+
|
|
75
|
+
if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
|
|
76
|
+
return lambda text, title='': pipe_pager(text, 'less', title)
|
|
77
|
+
|
|
78
|
+
import tempfile
|
|
79
|
+
(fd, filename) = tempfile.mkstemp()
|
|
80
|
+
os.close(fd)
|
|
81
|
+
try:
|
|
82
|
+
if hasattr(os, 'system') and os.system(f'more "{filename}"') == 0:
|
|
83
|
+
return lambda text, title='': pipe_pager(text, 'more', title)
|
|
84
|
+
|
|
85
|
+
else:
|
|
86
|
+
return tty_pager
|
|
87
|
+
|
|
88
|
+
finally:
|
|
89
|
+
os.unlink(filename)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def escape_stdout(text: str) -> str:
|
|
93
|
+
# Escape non-encodable characters to avoid encoding errors later
|
|
94
|
+
encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8'
|
|
95
|
+
return text.encode(encoding, 'backslashreplace').decode(encoding)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def escape_less(s: str) -> str:
|
|
99
|
+
return re.sub(r'([?:.%\\])', r'\\\1', s)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def plain(text: str) -> str:
|
|
103
|
+
"""Remove boldface formatting from text."""
|
|
104
|
+
|
|
105
|
+
return re.sub('.\b', '', text)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def tty_pager(text: str, title: str = '') -> None:
|
|
109
|
+
"""Page through text on a text terminal."""
|
|
110
|
+
|
|
111
|
+
lines = plain(escape_stdout(text)).split('\n')
|
|
112
|
+
has_tty = False
|
|
113
|
+
try:
|
|
114
|
+
fd = sys.stdin.fileno()
|
|
115
|
+
old = termios.tcgetattr(fd)
|
|
116
|
+
tty.setcbreak(fd)
|
|
117
|
+
has_tty = True
|
|
118
|
+
|
|
119
|
+
def getchar() -> str:
|
|
120
|
+
return sys.stdin.read(1)
|
|
121
|
+
|
|
122
|
+
except (ImportError, AttributeError, io.UnsupportedOperation):
|
|
123
|
+
def getchar() -> str:
|
|
124
|
+
return sys.stdin.readline()[:-1][:1]
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
try:
|
|
128
|
+
h = int(os.environ.get('LINES', '0'))
|
|
129
|
+
except ValueError:
|
|
130
|
+
h = 0
|
|
131
|
+
if h <= 1:
|
|
132
|
+
h = 25
|
|
133
|
+
r = inc = h - 1
|
|
134
|
+
|
|
135
|
+
sys.stdout.write('\n'.join(lines[:inc]) + '\n')
|
|
136
|
+
while lines[r:]:
|
|
137
|
+
sys.stdout.write('-- more --')
|
|
138
|
+
sys.stdout.flush()
|
|
139
|
+
c = getchar()
|
|
140
|
+
|
|
141
|
+
if c in ('q', 'Q'):
|
|
142
|
+
sys.stdout.write('\r \r')
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
elif c in ('\r', '\n'):
|
|
146
|
+
sys.stdout.write('\r \r' + lines[r] + '\n')
|
|
147
|
+
r = r + 1
|
|
148
|
+
continue
|
|
149
|
+
|
|
150
|
+
if c in ('b', 'B', '\x1b'):
|
|
151
|
+
r = r - inc - inc
|
|
152
|
+
if r < 0:
|
|
153
|
+
r = 0
|
|
154
|
+
|
|
155
|
+
sys.stdout.write('\n' + '\n'.join(lines[r:r + inc]) + '\n')
|
|
156
|
+
r = r + inc
|
|
157
|
+
|
|
158
|
+
finally:
|
|
159
|
+
if has_tty:
|
|
160
|
+
termios.tcsetattr(fd, termios.TCSAFLUSH, old) # noqa
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def plain_pager(text: str, title: str = '') -> None:
|
|
164
|
+
"""Simply print unformatted text. This is the ultimate fallback."""
|
|
165
|
+
|
|
166
|
+
sys.stdout.write(plain(escape_stdout(text)))
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def pipe_pager(text: str, cmd: str, title: str = '') -> None:
|
|
170
|
+
"""Page through text by feeding it to another program."""
|
|
171
|
+
|
|
172
|
+
env = os.environ.copy()
|
|
173
|
+
|
|
174
|
+
if title:
|
|
175
|
+
title += ' '
|
|
176
|
+
esc_title = escape_less(title)
|
|
177
|
+
|
|
178
|
+
prompt_string = (
|
|
179
|
+
f' {esc_title}'
|
|
180
|
+
'?ltline %lt?L/%L.'
|
|
181
|
+
':byte %bB?s/%s.'
|
|
182
|
+
'.'
|
|
183
|
+
'?e (END):?pB %pB\\%..'
|
|
184
|
+
' (press h for help or q to quit)'
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
env['LESS'] = f'-RmPm{prompt_string}$PM{prompt_string}$'
|
|
188
|
+
|
|
189
|
+
proc = subprocess.Popen(
|
|
190
|
+
cmd,
|
|
191
|
+
shell=True,
|
|
192
|
+
stdin=subprocess.PIPE,
|
|
193
|
+
errors='backslashreplace',
|
|
194
|
+
env=env,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
with check.not_none(proc.stdin) as pipe:
|
|
199
|
+
try:
|
|
200
|
+
pipe.write(text)
|
|
201
|
+
|
|
202
|
+
except KeyboardInterrupt:
|
|
203
|
+
# We've hereby abandoned whatever text hasn't been written, but the pager is still in control of the
|
|
204
|
+
# terminal.
|
|
205
|
+
pass
|
|
206
|
+
|
|
207
|
+
except OSError:
|
|
208
|
+
pass # Ignore broken pipes caused by quitting the pager program.
|
|
209
|
+
|
|
210
|
+
while True:
|
|
211
|
+
try:
|
|
212
|
+
proc.wait()
|
|
213
|
+
break
|
|
214
|
+
|
|
215
|
+
except KeyboardInterrupt:
|
|
216
|
+
# Ignore ctl-c like the pager itself does. Otherwise the pager is left running and the terminal is in raw
|
|
217
|
+
# mode and unusable.
|
|
218
|
+
pass
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def tempfile_pager(text: str, cmd: str, title: str = '') -> None:
|
|
222
|
+
"""Page through text by invoking a program on a temporary file."""
|
|
223
|
+
|
|
224
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
225
|
+
filename = os.path.join(tempdir, 'pydoc.out')
|
|
226
|
+
|
|
227
|
+
with open(
|
|
228
|
+
filename,
|
|
229
|
+
'w',
|
|
230
|
+
errors='backslashreplace',
|
|
231
|
+
encoding=os.device_encoding(0) if sys.platform == 'win32' else None,
|
|
232
|
+
) as file:
|
|
233
|
+
file.write(text)
|
|
234
|
+
|
|
235
|
+
os.system(cmd + ' "' + filename + '"')
|