cmdbox 0.5.0.4__py3-none-any.whl → 0.5.0.5__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 cmdbox might be problematic. Click here for more details.
- cmdbox/app/features/cli/cmdbox_gui_start.py +7 -0
- cmdbox/app/features/cli/cmdbox_web_start.py +9 -1
- cmdbox/app/web.py +30 -9
- cmdbox/version.py +2 -2
- {cmdbox-0.5.0.4.dist-info → cmdbox-0.5.0.5.dist-info}/METADATA +1 -1
- {cmdbox-0.5.0.4.dist-info → cmdbox-0.5.0.5.dist-info}/RECORD +10 -10
- {cmdbox-0.5.0.4.dist-info → cmdbox-0.5.0.5.dist-info}/LICENSE +0 -0
- {cmdbox-0.5.0.4.dist-info → cmdbox-0.5.0.5.dist-info}/WHEEL +0 -0
- {cmdbox-0.5.0.4.dist-info → cmdbox-0.5.0.5.dist-info}/entry_points.txt +0 -0
- {cmdbox-0.5.0.4.dist-info → cmdbox-0.5.0.5.dist-info}/top_level.txt +0 -0
|
@@ -4,6 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Dict, Any, Tuple, List, Union
|
|
5
5
|
import argparse
|
|
6
6
|
import logging
|
|
7
|
+
import multiprocessing
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class GuiStart(feature.UnsupportEdgeFeature):
|
|
@@ -88,6 +89,12 @@ class GuiStart(feature.UnsupportEdgeFeature):
|
|
|
88
89
|
dict(opt="session_timeout", type=Options.T_INT, default="600", required=False, multi=False, hide=True, choice=None,
|
|
89
90
|
discription_ja="サインインしたユーザーのセッションタイムアウトの時間を秒で指定します。",
|
|
90
91
|
discription_en="Specify the session timeout in seconds for signed-in users."),
|
|
92
|
+
dict(opt="guvicorn_workers", type=Options.T_INT, default=multiprocessing.cpu_count()*2, required=False, multi=False, hide=True, choice=None,
|
|
93
|
+
discription_ja="guvicornワーカー数を指定します。Linux環境でのみ有効です。-1又は未指定の場合はCPU数の2倍を使用します。",
|
|
94
|
+
discription_en="Specifies the number of guvicorn workers, valid only in Linux environment. If -1 or unspecified, twice the number of CPUs is used."),
|
|
95
|
+
dict(opt="guvicorn_timeout", type=Options.T_INT, default=30, required=False, multi=False, hide=True, choice=None,
|
|
96
|
+
discription_ja="guvicornワーカーのタイムアウトの時間を秒で指定します。",
|
|
97
|
+
discription_en="Specify the timeout duration of the guvicorn worker in seconds."),
|
|
91
98
|
dict(opt="client_only", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
92
99
|
discription_ja="サーバーへの接続を行わないようにします。",
|
|
93
100
|
discription_en="Do not make connections to the server."),
|
|
@@ -4,6 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Dict, Any, Tuple, List, Union
|
|
5
5
|
import argparse
|
|
6
6
|
import logging
|
|
7
|
+
import multiprocessing
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class WebStart(feature.UnsupportEdgeFeature):
|
|
@@ -88,6 +89,12 @@ class WebStart(feature.UnsupportEdgeFeature):
|
|
|
88
89
|
dict(opt="session_timeout", type=Options.T_INT, default="600", required=False, multi=False, hide=True, choice=None,
|
|
89
90
|
discription_ja="サインインしたユーザーのセッションタイムアウトの時間を秒で指定します。",
|
|
90
91
|
discription_en="Specify the session timeout in seconds for signed-in users."),
|
|
92
|
+
dict(opt="guvicorn_workers", type=Options.T_INT, default=multiprocessing.cpu_count()*2, required=False, multi=False, hide=True, choice=None,
|
|
93
|
+
discription_ja="guvicornワーカー数を指定します。Linux環境でのみ有効です。-1又は未指定の場合はCPU数の2倍を使用します。",
|
|
94
|
+
discription_en="Specifies the number of guvicorn workers, valid only in Linux environment. If -1 or unspecified, twice the number of CPUs is used."),
|
|
95
|
+
dict(opt="guvicorn_timeout", type=Options.T_INT, default=30, required=False, multi=False, hide=True, choice=None,
|
|
96
|
+
discription_ja="guvicornワーカーのタイムアウトの時間を秒で指定します。",
|
|
97
|
+
discription_en="Specify the timeout duration of the guvicorn worker in seconds."),
|
|
91
98
|
dict(opt="client_only", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
92
99
|
discription_ja="サーバーへの接続を行わないようにします。",
|
|
93
100
|
discription_en="Do not make connections to the server."),
|
|
@@ -158,7 +165,8 @@ class WebStart(feature.UnsupportEdgeFeature):
|
|
|
158
165
|
ssl_cert=ssl_cert, ssl_key=ssl_key, ssl_keypass=args.ssl_keypass, ssl_ca_certs=ssl_ca_certs,
|
|
159
166
|
session_domain=args.session_domain, session_path=args.session_path,
|
|
160
167
|
session_secure=args.session_secure, session_timeout=args.session_timeout,
|
|
161
|
-
outputs_key=args.outputs_key)
|
|
168
|
+
outputs_key=args.outputs_key, guvicorn_workers=args.guvicorn_workers, guvicorn_timeout=args.guvicorn_timeout)
|
|
169
|
+
|
|
162
170
|
msg = dict(success="web complate.")
|
|
163
171
|
common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
|
|
164
172
|
return 0, msg, w
|
cmdbox/app/web.py
CHANGED
|
@@ -12,6 +12,7 @@ import ctypes
|
|
|
12
12
|
import datetime
|
|
13
13
|
import gevent
|
|
14
14
|
import logging
|
|
15
|
+
import multiprocessing
|
|
15
16
|
import os
|
|
16
17
|
import platform
|
|
17
18
|
import requests
|
|
@@ -1136,7 +1137,8 @@ class Web:
|
|
|
1136
1137
|
|
|
1137
1138
|
def start(self, allow_host:str="0.0.0.0", listen_port:int=8081, ssl_listen_port:int=8443,
|
|
1138
1139
|
ssl_cert:Path=None, ssl_key:Path=None, ssl_keypass:str=None, ssl_ca_certs:Path=None,
|
|
1139
|
-
session_domain:str=None, session_path:str='/', session_secure:bool=False, session_timeout:int=600, outputs_key:List[str]=[]
|
|
1140
|
+
session_domain:str=None, session_path:str='/', session_secure:bool=False, session_timeout:int=600, outputs_key:List[str]=[],
|
|
1141
|
+
guvicorn_workers:int=-1, guvicorn_timeout:int=30):
|
|
1140
1142
|
"""
|
|
1141
1143
|
Webサーバを起動する
|
|
1142
1144
|
|
|
@@ -1153,6 +1155,8 @@ class Web:
|
|
|
1153
1155
|
session_secure (bool, optional): セッションセキュア. Defaults to False.
|
|
1154
1156
|
session_timeout (int, optional): セッションタイムアウト. Defaults to 600.
|
|
1155
1157
|
outputs_key (list, optional): 出力キー. Defaults to [].
|
|
1158
|
+
guvicorn_workers (int, optional): Gunicornワーカー数. Defaults to -1.
|
|
1159
|
+
guvicorn_timeout (int, optional): Gunicornタイムアウト. Defaults to 30.
|
|
1156
1160
|
"""
|
|
1157
1161
|
self.allow_host = allow_host
|
|
1158
1162
|
self.listen_port = listen_port
|
|
@@ -1166,6 +1170,8 @@ class Web:
|
|
|
1166
1170
|
self.session_path = session_path
|
|
1167
1171
|
self.session_secure = session_secure
|
|
1168
1172
|
self.session_timeout = session_timeout
|
|
1173
|
+
self.guvicorn_workers = guvicorn_workers
|
|
1174
|
+
self.guvicorn_timeout = guvicorn_timeout
|
|
1169
1175
|
if self.logger.level == logging.DEBUG:
|
|
1170
1176
|
self.logger.debug(f"web start parameter: allow_host={self.allow_host}")
|
|
1171
1177
|
self.logger.debug(f"web start parameter: listen_port={self.listen_port}")
|
|
@@ -1179,6 +1185,8 @@ class Web:
|
|
|
1179
1185
|
self.logger.debug(f"web start parameter: session_path={self.session_path}")
|
|
1180
1186
|
self.logger.debug(f"web start parameter: session_secure={self.session_secure}")
|
|
1181
1187
|
self.logger.debug(f"web start parameter: session_timeout={self.session_timeout}")
|
|
1188
|
+
self.logger.debug(f"web start parameter: guvicorn_worker={self.guvicorn_workers}")
|
|
1189
|
+
self.logger.debug(f"web start parameter: guvicorn_timeout={self.guvicorn_timeout}")
|
|
1182
1190
|
|
|
1183
1191
|
app = FastAPI()
|
|
1184
1192
|
mwparam = dict(path=self.session_path, max_age=self.session_timeout, secret_key=common.random_string())
|
|
@@ -1191,7 +1199,8 @@ class Web:
|
|
|
1191
1199
|
|
|
1192
1200
|
self.is_running = True
|
|
1193
1201
|
#uvicorn.run(app, host=self.allow_host, port=self.listen_port, workers=2)
|
|
1194
|
-
th = ThreadedUvicorn(self.logger, config=Config(app=app, host=self.allow_host, port=self.listen_port)
|
|
1202
|
+
th = ThreadedUvicorn(self.logger, config=Config(app=app, host=self.allow_host, port=self.listen_port),
|
|
1203
|
+
guvicorn_config=dict(workers=self.guvicorn_workers, timeout=self.guvicorn_timeout))
|
|
1195
1204
|
th.start()
|
|
1196
1205
|
browser_port = self.listen_port
|
|
1197
1206
|
th_ssl = None
|
|
@@ -1199,7 +1208,8 @@ class Web:
|
|
|
1199
1208
|
th_ssl = ThreadedUvicorn(self.logger,
|
|
1200
1209
|
config=Config(app=app, host=self.allow_host, port=self.ssl_listen_port,
|
|
1201
1210
|
ssl_certfile=self.ssl_cert, ssl_keyfile=self.ssl_key,
|
|
1202
|
-
ssl_keyfile_password=self.ssl_keypass, ssl_ca_certs=self.ssl_ca_certs)
|
|
1211
|
+
ssl_keyfile_password=self.ssl_keypass, ssl_ca_certs=self.ssl_ca_certs),
|
|
1212
|
+
guvicorn_config=dict(workers=self.guvicorn_workers, timeout=self.guvicorn_timeout))
|
|
1203
1213
|
th_ssl.start()
|
|
1204
1214
|
browser_port = self.ssl_listen_port
|
|
1205
1215
|
try:
|
|
@@ -1236,34 +1246,45 @@ class Web:
|
|
|
1236
1246
|
self.logger.info(f"Exit web.")
|
|
1237
1247
|
|
|
1238
1248
|
class ThreadedUvicorn:
|
|
1239
|
-
def __init__(self, logger:logging.Logger, config:Config):
|
|
1249
|
+
def __init__(self, logger:logging.Logger, config:Config, guvicorn_config:Dict[str, Any]):
|
|
1240
1250
|
self.logger = logger
|
|
1251
|
+
self.guvicorn_config = guvicorn_config
|
|
1241
1252
|
if platform.system() == "Windows":
|
|
1242
1253
|
self.server = uvicorn.Server(config)
|
|
1243
1254
|
self.thread = RaiseThread(daemon=True, target=self.server.run)
|
|
1244
1255
|
else:
|
|
1245
1256
|
from gunicorn.app.wsgiapp import WSGIApplication
|
|
1246
|
-
import multiprocessing
|
|
1247
1257
|
class App(WSGIApplication):
|
|
1248
|
-
def __init__(self, app, options
|
|
1249
|
-
self.options = options
|
|
1258
|
+
def __init__(self, app, options):
|
|
1259
|
+
self.options = options
|
|
1250
1260
|
self.application = app
|
|
1251
1261
|
self.started = True
|
|
1252
1262
|
super().__init__()
|
|
1253
1263
|
def load_config(self):
|
|
1254
|
-
config = {
|
|
1264
|
+
config = {k: v for k, v in self.options.items() if k in self.cfg.settings and v is not None}
|
|
1255
1265
|
for key, value in config.items():
|
|
1256
1266
|
self.cfg.set(key.lower(), value)
|
|
1257
1267
|
def load(self):
|
|
1258
1268
|
return self.application
|
|
1259
1269
|
opt = dict(bind=f"{config.host}:{config.port}",
|
|
1260
|
-
workers=multiprocessing.cpu_count()*2,
|
|
1261
1270
|
worker_class="uvicorn.workers.UvicornWorker",
|
|
1262
1271
|
access_log_format='[%(t)s] %(p)s %(l)s %(h)s "%(r)s" %(s)s',
|
|
1263
1272
|
loglevel=logging.getLevelName(self.logger.level),
|
|
1264
1273
|
keyfile=config.ssl_keyfile, certfile=config.ssl_certfile,
|
|
1265
1274
|
ca_certs=config.ssl_ca_certs, keyfile_password=config.ssl_keyfile_password,
|
|
1266
1275
|
limit_request_line=8190, limit_request_fields=100, limit_request_field_size=8190)
|
|
1276
|
+
|
|
1277
|
+
self.guvicorn_config = self.guvicorn_config or {}
|
|
1278
|
+
if 'workers' not in self.guvicorn_config:
|
|
1279
|
+
self.guvicorn_config['workers'] = None
|
|
1280
|
+
if self.guvicorn_config['workers'] is None or self.guvicorn_config['workers'] <= 0:
|
|
1281
|
+
self.guvicorn_config['workers'] = multiprocessing.cpu_count()*2
|
|
1282
|
+
if 'timeout' not in self.guvicorn_config:
|
|
1283
|
+
self.guvicorn_config['timeout'] = None
|
|
1284
|
+
if self.guvicorn_config['timeout'] is None or self.guvicorn_config['timeout'] <= 0:
|
|
1285
|
+
self.guvicorn_config['timeout'] = 30
|
|
1286
|
+
|
|
1287
|
+
opt = {**opt, **self.guvicorn_config}
|
|
1267
1288
|
self.server = App(config.app, opt)
|
|
1268
1289
|
#self.thread = RaiseThread(daemon=True, target=self.server.run)
|
|
1269
1290
|
|
cmdbox/version.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
|
|
3
|
-
dt_now = datetime.datetime(2025, 3,
|
|
3
|
+
dt_now = datetime.datetime(2025, 3, 11)
|
|
4
4
|
__appid__ = 'cmdbox'
|
|
5
5
|
__title__ = 'cmdbox (Command Development Application)'
|
|
6
|
-
__version__ = '0.5.0.
|
|
6
|
+
__version__ = '0.5.0.5'
|
|
7
7
|
__copyright__ = f'Copyright © 2023-{dt_now.strftime("%Y")} hamacom2004jp'
|
|
8
8
|
__pypiurl__ = 'https://pypi.org/project/cmdbox/'
|
|
9
9
|
__srcurl__ = 'https://github.com/hamacom2004jp/cmdbox'
|
|
@@ -6,7 +6,7 @@ cmdbox/logconf_edge.yml,sha256=RkbUebCJV2z5dLnpgvf4GSFkd-Blzu4vUUDP9CQFwdM,686
|
|
|
6
6
|
cmdbox/logconf_gui.yml,sha256=T3yhWoiyp0DW06RjiFG6kS7jScqXYs-KLfC5EYKUImk,686
|
|
7
7
|
cmdbox/logconf_server.yml,sha256=tpDpKQXgTWzUnHKGU-Vvsha7n1hyIyFdLnSeCgnOgyk,701
|
|
8
8
|
cmdbox/logconf_web.yml,sha256=lzr3ytjqRbQutbhEOJdHJT0hrrR_h9sPkaEQkzX02lo,686
|
|
9
|
-
cmdbox/version.py,sha256=
|
|
9
|
+
cmdbox/version.py,sha256=4Ccsz3DWtdZ7xn-dg9rNj01Ndhejo7WvGZEb_085XOQ,1963
|
|
10
10
|
cmdbox/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
cmdbox/app/app.py,sha256=2rQpTbezCLuy36df89EhKsAfcPjtGepGHSTQZXimcqA,8949
|
|
12
12
|
cmdbox/app/client.py,sha256=SNM4xxDh5ARxV6I7cDrmbzGc7sXUUwB3tSyIksdT1RY,19562
|
|
@@ -17,7 +17,7 @@ cmdbox/app/filer.py,sha256=L_DSMTvnbN_ffr3JIt0obbOmVoTHEfVm2cAVz3rLH-Q,16059
|
|
|
17
17
|
cmdbox/app/options.py,sha256=A4q4dAFAsTaV_k4z7n7hT2Dl6Ei6DrQ7X0xKoVDK6sM,31092
|
|
18
18
|
cmdbox/app/server.py,sha256=rrH_a6zzrx7glp_SqRrc_2gBgRoT9FX0F1bpGxVLX1I,9467
|
|
19
19
|
cmdbox/app/signin.py,sha256=Ry4jxUuroOAIAfTYSolMm_izaF27-IS7914I4vhr6yU,2577
|
|
20
|
-
cmdbox/app/web.py,sha256=
|
|
20
|
+
cmdbox/app/web.py,sha256=6MXgl_lb4MZO8Lq1kZnGNiIZw6d0eO4c9T-izD_XzZY,80017
|
|
21
21
|
cmdbox/app/commons/convert.py,sha256=etWeutkPyE8FMz11jw4KJ5uip7qu_CoD1yIqF5iypgg,6754
|
|
22
22
|
cmdbox/app/commons/loghandler.py,sha256=TQXXg8KdAzHMPwSQGq7RP0qTHxb35PhUTqqDFWkimgk,3306
|
|
23
23
|
cmdbox/app/commons/module.py,sha256=RsEyqP9Qty4v0qIEE6VuY4pgMlkhJKNTUhsN5p-sSoM,4880
|
|
@@ -33,7 +33,7 @@ cmdbox/app/features/cli/cmdbox_client_file_upload.py,sha256=w8vbNttQ_V-R3UWkj0iK
|
|
|
33
33
|
cmdbox/app/features/cli/cmdbox_client_server_info.py,sha256=6cCWFoFF0stCw7Mn57LUFgUDCKFPThzAerTMuYnLc-I,9398
|
|
34
34
|
cmdbox/app/features/cli/cmdbox_edge_config.py,sha256=CzuF4YlngUTOBOr6jDAe-jzQ-psb9OVXMxIEtjKddYQ,7240
|
|
35
35
|
cmdbox/app/features/cli/cmdbox_edge_start.py,sha256=SWI0SEdergvVBuewyypH5cWrCZSm_M365RRkGxSLqB8,3849
|
|
36
|
-
cmdbox/app/features/cli/cmdbox_gui_start.py,sha256=
|
|
36
|
+
cmdbox/app/features/cli/cmdbox_gui_start.py,sha256=A15Iol1nRCd_kTMKTyM-uKYEnEd3I_ZYPQRI8fw6Tks,14403
|
|
37
37
|
cmdbox/app/features/cli/cmdbox_gui_stop.py,sha256=nxaKEM_JSbndcbuHo2CSv7XX4hQwSf3_XC_aasVcs_Y,2730
|
|
38
38
|
cmdbox/app/features/cli/cmdbox_server_list.py,sha256=xinPmftRK2WkhuZiC6RPh7ldbqEpYErbNaWZSUcT03I,5689
|
|
39
39
|
cmdbox/app/features/cli/cmdbox_server_start.py,sha256=2u-J5GlkJxX7a6Sh8Gw8OfsbhkzYz4zhDGXEtSd2CwM,7294
|
|
@@ -46,7 +46,7 @@ cmdbox/app/features/cli/cmdbox_web_group_add.py,sha256=pxhR1Pg-EngB3vQmPnAUys4EV
|
|
|
46
46
|
cmdbox/app/features/cli/cmdbox_web_group_del.py,sha256=nQfS2zgqDGTZaMdiEZvscIqF84k2Kf_9cwt_aqeJmAE,6597
|
|
47
47
|
cmdbox/app/features/cli/cmdbox_web_group_edit.py,sha256=M-B3txvtLc4sh6URFWVaHaDJCdz3MrLwkmQKSZ2mr-o,7326
|
|
48
48
|
cmdbox/app/features/cli/cmdbox_web_group_list.py,sha256=sSj237xq5ZrvBSVh2w7ZDHwbzdDR1oJDwmaCfqbp808,6692
|
|
49
|
-
cmdbox/app/features/cli/cmdbox_web_start.py,sha256=
|
|
49
|
+
cmdbox/app/features/cli/cmdbox_web_start.py,sha256=aa4TncMVK3cbXDOSYhJ_N__WZziXzbYBIW3b6Fn3nr0,15272
|
|
50
50
|
cmdbox/app/features/cli/cmdbox_web_stop.py,sha256=mGFRgTvm4lbt9D9O-Gnp3p0E44KQ9TyURMYk_ngTWto,3593
|
|
51
51
|
cmdbox/app/features/cli/cmdbox_web_user_add.py,sha256=agMXexo99lKALEo4nAQA9BDFN1oTmu8_nCjWL6BSGuc,8547
|
|
52
52
|
cmdbox/app/features/cli/cmdbox_web_user_del.py,sha256=kj1te2Sogdg8huVPbuVa_a6EBR9sJ6kbmw4VgSRHkaY,6560
|
|
@@ -248,9 +248,9 @@ cmdbox/web/assets/tree-menu/image/file.png,sha256=Uw4zYkHyuoZ_kSVkesHAeSeA_g9_LP
|
|
|
248
248
|
cmdbox/web/assets/tree-menu/image/folder-close.png,sha256=TcgsKTBBF2ejgzekOEDBFBxsJf-Z5u0x9IZVi4GBR-I,284
|
|
249
249
|
cmdbox/web/assets/tree-menu/image/folder-open.png,sha256=DT7y1GRK4oXJkFvqTN_oSGM5ZYARzPvjoCGL6wqkoo0,301
|
|
250
250
|
cmdbox/web/assets/tree-menu/js/tree-menu.js,sha256=-GkZxI7xzHuXXHYQBHAVTcuKX4TtoiMuyIms6Xc3pxk,1029
|
|
251
|
-
cmdbox-0.5.0.
|
|
252
|
-
cmdbox-0.5.0.
|
|
253
|
-
cmdbox-0.5.0.
|
|
254
|
-
cmdbox-0.5.0.
|
|
255
|
-
cmdbox-0.5.0.
|
|
256
|
-
cmdbox-0.5.0.
|
|
251
|
+
cmdbox-0.5.0.5.dist-info/LICENSE,sha256=sBzzPc5v-5LBuIFi2V4olsnoVg-3EBI0zRX5r19SOxE,1117
|
|
252
|
+
cmdbox-0.5.0.5.dist-info/METADATA,sha256=8Gn7XHd-1DqfMVnMAaknymWNbYMJ-fqXfWuepfw1O6M,24050
|
|
253
|
+
cmdbox-0.5.0.5.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
254
|
+
cmdbox-0.5.0.5.dist-info/entry_points.txt,sha256=PIoRz-tr503YwdMmd6nxuSn2dDltf4cUMVs98E9WgaA,48
|
|
255
|
+
cmdbox-0.5.0.5.dist-info/top_level.txt,sha256=eMEkD5jn8_0PkCAL8h5xJu4qAzF2O8Wf3vegFkKUXR4,7
|
|
256
|
+
cmdbox-0.5.0.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|