cmdbox 0.6.4.2__py3-none-any.whl → 0.6.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/app.py +7 -0
- cmdbox/app/client.py +4 -3
- cmdbox/app/common.py +85 -7
- cmdbox/app/commons/convert.py +3 -1
- cmdbox/app/edge.py +12 -12
- cmdbox/app/features/cli/{cmdbox_vision_install.py → _cmdbox_vision_install.py} +2 -1
- cmdbox/app/features/cli/_cmdbox_vision_predict.py +496 -0
- cmdbox/app/features/cli/{cmdbox_vision_start.py → _cmdbox_vision_start.py} +5 -1
- cmdbox/app/features/cli/cmdbox_cmd_list.py +3 -3
- cmdbox/app/features/cli/cmdbox_cmd_load.py +3 -3
- cmdbox/app/features/cli/cmdbox_tts_install.py +4 -2
- cmdbox/app/features/cli/cmdbox_tts_say.py +2 -1
- cmdbox/app/features/cli/cmdbox_web_apikey_add.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_apikey_del.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_group_add.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_group_del.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_group_edit.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_group_list.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_start.py +10 -10
- cmdbox/app/features/cli/cmdbox_web_user_add.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_user_del.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_user_edit.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_user_list.py +3 -3
- cmdbox/app/features/web/cmdbox_web_exec_cmd.py +12 -14
- cmdbox/app/filer.py +5 -2
- cmdbox/app/mcp.py +4 -3
- cmdbox/app/options.py +8 -0
- cmdbox/app/web.py +50 -36
- cmdbox/licenses/LICENSE_Hypercorn_0_17_3_MIT_License.txt +22 -0
- cmdbox/licenses/{LICENSE_cffi_1_17_1_MIT_License.txt → LICENSE_cffi_2_0_0_UNKNOWN.txt} +2 -5
- cmdbox/licenses/{LICENSE_jsonschema-specifications_2025_4_1_UNKNOWN.txt → LICENSE_h2_4_3_0_MIT_License.txt} +3 -1
- cmdbox/licenses/{LICENSE_backoff_2_2_1_MIT_License.txt → LICENSE_hpack_4_1_0_MIT_License.txt} +1 -1
- cmdbox/licenses/{LICENSE_graphviz_0_21_UNKNOWN.txt → LICENSE_hyperframe_6_1_0_MIT_License.txt} +1 -1
- cmdbox/licenses/{LICENSE_jsonschema_4_25_0_UNKNOWN.txt → LICENSE_priority_2_0_0_MIT_License.txt} +2 -2
- cmdbox/licenses/files.txt +26 -147
- cmdbox/version.py +2 -2
- cmdbox/web/assets/cmdbox/svgicon.js +9 -0
- {cmdbox-0.6.4.2.dist-info → cmdbox-0.6.5.dist-info}/METADATA +3 -1
- {cmdbox-0.6.4.2.dist-info → cmdbox-0.6.5.dist-info}/RECORD +63 -163
- cmdbox/app/features/cli/cmdbox_vision_predict.py +0 -192
- cmdbox/licenses/LICENSE_APScheduler_3_11_0_MIT_License.txt +0 -19
- cmdbox/licenses/LICENSE_Authlib_1_6_1_BSD_License.txt +0 -29
- cmdbox/licenses/LICENSE_SQLAlchemy_2_0_43_MIT.txt +0 -19
- cmdbox/licenses/LICENSE_Werkzeug_3_1_1_BSD_License.txt +0 -28
- cmdbox/licenses/LICENSE_absolufy-imports_0_3_1_MIT_License.txt +0 -21
- cmdbox/licenses/LICENSE_aiohttp_3_12_15_Apache-2_0_AND_MIT.txt +0 -13
- cmdbox/licenses/LICENSE_aiosignal_1_4_0_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_attrs_25_3_0_UNKNOWN.txt +0 -21
- cmdbox/licenses/LICENSE_cachetools_5_5_2_MIT_License.txt +0 -20
- cmdbox/licenses/LICENSE_cloudpickle_3_1_1_BSD_License.txt +0 -1
- cmdbox/licenses/LICENSE_cyclopts_3_22_5_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_distro_1_9_0_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_dnspython_2_7_0_ISC_License-ISCL.txt +0 -35
- cmdbox/licenses/LICENSE_docstring_parser_0_17_0_MIT_License.txt +0 -21
- cmdbox/licenses/LICENSE_email_validator_2_2_0_The_Unlicense-Unlicense.txt +0 -27
- cmdbox/licenses/LICENSE_exceptiongroup_1_3_0_MIT_License.txt +0 -73
- cmdbox/licenses/LICENSE_fastapi-sso_0_18_0_MIT_License.txt +0 -21
- cmdbox/licenses/LICENSE_fastmcp_2_11_3_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_filelock_3_18_0_The_Unlicense-Unlicense.txt +0 -24
- cmdbox/licenses/LICENSE_frozenlist_1_7_0_Apache-2_0.txt +0 -201
- cmdbox/licenses/LICENSE_fsspec_2025_7_0_BSD_License.txt +0 -29
- cmdbox/licenses/LICENSE_google-adk_1_10_0_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-api-core_2_25_1_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-api-python-client_2_178_0_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_google-auth-httplib2_0_2_0_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_google-auth_2_40_3_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_google-cloud-aiplatform_1_108_0_Apache_2_0.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-appengine-logging_1_6_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-audit-log_0_3_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-bigquery_3_35_1_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-core_2_4_3_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-logging_3_12_1_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-resource-manager_1_14_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-secret-manager_2_24_0_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-speech_2_33_0_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-storage_2_19_0_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-cloud-trace_1_16_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-crc32c_1_7_1_Apache_2_0.txt +0 -202
- cmdbox/licenses/LICENSE_google-genai_1_29_0_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_google-resumable-media_2_7_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_googleapis-common-protos_1_70_0_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_grpc-google-iam-v1_0_14_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_grpcio-status_1_74_0_Apache_Software_License.txt +0 -610
- cmdbox/licenses/LICENSE_grpcio_1_74_0_Apache_Software_License.txt +0 -610
- cmdbox/licenses/LICENSE_httpcore_1_0_9_BSD_License.txt +0 -27
- cmdbox/licenses/LICENSE_httplib2_0_22_0_MIT_License.txt +0 -23
- cmdbox/licenses/LICENSE_httpx-sse_0_4_1_MIT.txt +0 -21
- cmdbox/licenses/LICENSE_httpx_0_28_1_BSD_License.txt +0 -12
- cmdbox/licenses/LICENSE_huggingface-hub_0_34_4_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_isodate_0_7_2_BSD_License.txt +0 -26
- cmdbox/licenses/LICENSE_jiter_0_10_0_MIT_License.txt +0 -1
- cmdbox/licenses/LICENSE_jsonschema-path_0_3_4_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_lazy-object-proxy_1_11_0_BSD_License.txt +0 -20
- cmdbox/licenses/LICENSE_litellm-enterprise_0_1_19_UNKNOWN.txt +0 -37
- cmdbox/licenses/LICENSE_litellm_1_75_5_post1_MIT_License.txt +0 -26
- cmdbox/licenses/LICENSE_mcp_1_12_4_MIT_License.txt +0 -21
- cmdbox/licenses/LICENSE_multidict_6_6_4_Apache_License_2_0.txt +0 -13
- cmdbox/licenses/LICENSE_oauthlib_3_3_1_BSD-3-Clause.txt +0 -27
- cmdbox/licenses/LICENSE_openai_1_99_9_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_openapi-core_0_19_5_BSD_License.txt +0 -29
- cmdbox/licenses/LICENSE_openapi-pydantic_0_5_1_MIT_License.txt +0 -40
- cmdbox/licenses/LICENSE_openapi-schema-validator_0_6_3_BSD_License.txt +0 -29
- cmdbox/licenses/LICENSE_openapi-spec-validator_0_7_2_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_opentelemetry-api_1_36_0_UNKNOWN.txt +0 -201
- cmdbox/licenses/LICENSE_opentelemetry-exporter-gcp-trace_1_9_0_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_opentelemetry-resourcedetector-gcp_1_9_0a0_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_opentelemetry-sdk_1_36_0_UNKNOWN.txt +0 -201
- cmdbox/licenses/LICENSE_opentelemetry-semantic-conventions_0_57b0_UNKNOWN.txt +0 -201
- cmdbox/licenses/LICENSE_orjson_3_11_1_Apache_Software_License-MIT_License.txt +0 -201
- cmdbox/licenses/LICENSE_parse_1_20_2_MIT_License.txt +0 -19
- cmdbox/licenses/LICENSE_pathable_0_4_4_Apache_Software_License.txt +0 -201
- cmdbox/licenses/LICENSE_propcache_0_3_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_proto-plus_1_26_1_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_protobuf_6_31_1_3-Clause_BSD_License.txt +0 -32
- cmdbox/licenses/LICENSE_pyasn1_0_6_1_BSD_License.txt +0 -24
- cmdbox/licenses/LICENSE_pyasn1_modules_0_4_2_BSD_License.txt +0 -24
- cmdbox/licenses/LICENSE_pydantic-settings_2_10_1_MIT_License.txt +0 -21
- cmdbox/licenses/LICENSE_pyparsing_3_2_3_MIT_License.txt +0 -18
- cmdbox/licenses/LICENSE_pyperclip_1_9_0_BSD_License.txt +0 -27
- cmdbox/licenses/LICENSE_python-dateutil_2_9_0_post0_Apache_Software_License-BSD_License.txt +0 -54
- cmdbox/licenses/LICENSE_python-dotenv_1_1_1_BSD_License.txt +0 -27
- cmdbox/licenses/LICENSE_pywin32_311_Python_Software_Foundation_License.txt +0 -1
- cmdbox/licenses/LICENSE_referencing_0_36_2_UNKNOWN.txt +0 -19
- cmdbox/licenses/LICENSE_regex_2025_7_34_UNKNOWN.txt +0 -208
- cmdbox/licenses/LICENSE_rfc3339-validator_0_1_4_MIT_License.txt +0 -22
- cmdbox/licenses/LICENSE_rich-rst_1_3_1_MIT_License.txt +0 -7
- cmdbox/licenses/LICENSE_rpds-py_0_27_0_UNKNOWN.txt +0 -19
- cmdbox/licenses/LICENSE_rsa_4_9_1_Apache_Software_License.txt +0 -13
- cmdbox/licenses/LICENSE_shapely_2_1_1_BSD_License.txt +0 -29
- cmdbox/licenses/LICENSE_sse-starlette_3_0_2_UNKNOWN.txt +0 -27
- cmdbox/licenses/LICENSE_tenacity_9_1_2_Apache_Software_License.txt +0 -202
- cmdbox/licenses/LICENSE_tiktoken_0_11_0_MIT_License-Copyright-c-2022_OpenAI-Shantanu_Jain-Permission_is_hereby_granted-free_of_charge-to_any_per.txt +0 -21
- cmdbox/licenses/LICENSE_tokenizers_0_21_4_Apache_Software_License.txt +0 -1
- cmdbox/licenses/LICENSE_tqdm_4_67_1_MIT_License-Mozilla_Public_License_2_0-MPL_2_0.txt +0 -49
- cmdbox/licenses/LICENSE_typing_extensions_4_14_1_UNKNOWN.txt +0 -279
- cmdbox/licenses/LICENSE_tzlocal_5_3_1_MIT_License.txt +0 -19
- cmdbox/licenses/LICENSE_uritemplate_4_2_0_BSD_3-Clause_OR_Apache-2_0.txt +0 -3
- cmdbox/licenses/LICENSE_uvicorn_0_35_0_BSD_License.txt +0 -27
- cmdbox/licenses/LICENSE_watchdog_6_0_0_Apache_Software_License.txt +0 -16
- cmdbox/licenses/LICENSE_websockets_15_0_1_BSD_License.txt +0 -24
- cmdbox/licenses/LICENSE_yarl_1_20_1_Apache_Software_License.txt +0 -202
- /cmdbox/licenses/{LICENSE_click_8_2_1_UNKNOWN.txt → LICENSE_click_8_3_0_UNKNOWN.txt} +0 -0
- /cmdbox/licenses/{LICENSE_cryptography_45_0_6_Apache-2_0_OR_BSD-3-Clause.txt → LICENSE_cryptography_46_0_1_UNKNOWN.txt} +0 -0
- /cmdbox/licenses/{LICENSE_fastapi_0_116_1_MIT_License.txt → LICENSE_fastapi_0_116_2_MIT_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_gevent_25_5_1_MIT.txt → LICENSE_gevent_25_9_1_MIT.txt} +0 -0
- /cmdbox/licenses/{LICENSE_jaraco_functools_4_2_1_UNKNOWN.txt → LICENSE_jaraco_functools_4_3_0_UNKNOWN.txt} +0 -0
- /cmdbox/licenses/{LICENSE_more-itertools_10_7_0_MIT_License.txt → LICENSE_more-itertools_10_8_0_UNKNOWN.txt} +0 -0
- /cmdbox/licenses/{LICENSE_numpy_2_3_2_BSD_License.txt → LICENSE_numpy_2_3_3_BSD_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_prompt_toolkit_3_0_51_BSD_License.txt → LICENSE_prompt_toolkit_3_0_52_BSD_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_psycopg-binary_3_2_9_GNU_Lesser_General_Public_License_v3-LGPLv3.txt → LICENSE_psycopg-binary_3_2_10_GNU_Lesser_General_Public_License_v3-LGPLv3.txt} +0 -0
- /cmdbox/licenses/{LICENSE_psycopg_3_2_9_GNU_Lesser_General_Public_License_v3-LGPLv3.txt → LICENSE_psycopg_3_2_10_GNU_Lesser_General_Public_License_v3-LGPLv3.txt} +0 -0
- /cmdbox/licenses/{LICENSE_pycparser_2_22_BSD_License.txt → LICENSE_pycparser_2_23_BSD_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_pydantic_2_11_7_MIT_License.txt → LICENSE_pydantic_2_11_9_MIT_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_questionary_2_1_0_MIT_License.txt → LICENSE_questionary_2_1_1_MIT_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_requests_2_32_4_Apache_Software_License.txt → LICENSE_requests_2_32_5_Apache_Software_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_sphinx-sitemap_2_7_2_UNKNOWN.txt → LICENSE_sphinx-sitemap_2_8_0_UNKNOWN.txt} +0 -0
- /cmdbox/licenses/{LICENSE_starlette_0_47_2_BSD_License.txt → LICENSE_starlette_0_48_0_BSD_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_twine_6_1_0_Apache_Software_License.txt → LICENSE_twine_6_2_0_UNKNOWN.txt} +0 -0
- /cmdbox/licenses/{LICENSE_aiohappyeyeballs_2_6_1_Python_Software_Foundation_License.txt → LICENSE_typing_extensions_4_15_0_UNKNOWN.txt} +0 -0
- /cmdbox/licenses/{LICENSE_zope_event_5_1_1_Zope_Public_License.txt → LICENSE_zope_event_6_0_Zope_Public_License.txt} +0 -0
- /cmdbox/licenses/{LICENSE_zope_interface_7_2_Zope_Public_License.txt → LICENSE_zope_interface_8_0_Zope_Public_License.txt} +0 -0
- {cmdbox-0.6.4.2.dist-info → cmdbox-0.6.5.dist-info}/WHEEL +0 -0
- {cmdbox-0.6.4.2.dist-info → cmdbox-0.6.5.dist-info}/entry_points.txt +0 -0
- {cmdbox-0.6.4.2.dist-info → cmdbox-0.6.5.dist-info}/licenses/LICENSE +0 -0
- {cmdbox-0.6.4.2.dist-info → cmdbox-0.6.5.dist-info}/top_level.txt +0 -0
|
@@ -40,9 +40,9 @@ class WebGroupDel(feature.UnsupportEdgeFeature):
|
|
|
40
40
|
dict(opt="group_id", type=Options.T_INT, default=None, required=True, multi=False, hide=False, choice=None,
|
|
41
41
|
description_ja="グループIDを指定します。",
|
|
42
42
|
description_en="Specify the group ID. Do not duplicate other groups."),
|
|
43
|
-
dict(opt="signin_file", type=Options.T_FILE, default=
|
|
44
|
-
description_ja="
|
|
45
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
43
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=True, multi=False, hide=False, choice=None, fileio="in",
|
|
44
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
45
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
46
46
|
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
47
47
|
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
48
48
|
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
@@ -46,9 +46,9 @@ class WebGroupEdit(feature.UnsupportEdgeFeature):
|
|
|
46
46
|
dict(opt="group_parent", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
47
47
|
description_ja="親グループ名を指定します。",
|
|
48
48
|
description_en="Specifies the parent group name."),
|
|
49
|
-
dict(opt="signin_file", type=Options.T_FILE, default=
|
|
50
|
-
description_ja="
|
|
51
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
49
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=True, multi=False, hide=False, choice=None, fileio="in",
|
|
50
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
51
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
52
52
|
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
53
53
|
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
54
54
|
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
@@ -40,9 +40,9 @@ class WebGroupList(feature.UnsupportEdgeFeature):
|
|
|
40
40
|
dict(opt="group_name", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
41
41
|
description_ja="グループ名を指定して取得します。省略した時は全てのグループを取得します。",
|
|
42
42
|
description_en="Retrieved by specifying a group name. If omitted, all groups are retrieved."),
|
|
43
|
-
dict(opt="signin_file", type=Options.T_FILE, default=
|
|
44
|
-
description_ja="
|
|
45
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
43
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=True, multi=False, hide=False, choice=None, fileio="in",
|
|
44
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
45
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
46
46
|
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
47
47
|
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
48
48
|
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
@@ -78,9 +78,9 @@ class WebStart(feature.UnsupportEdgeFeature, agent_base.AgentBase):
|
|
|
78
78
|
dict(opt="ssl_ca_certs", type=Options.T_FILE, default=None, required=False, multi=False, hide=True, choice=None, fileio="in",
|
|
79
79
|
description_ja="SSLサーバーCA証明書ファイルを指定します。",
|
|
80
80
|
description_en="Specify the SSL server CA certificate file."),
|
|
81
|
-
dict(opt="signin_file", type=Options.T_FILE, default=None, required=False, multi=False, hide=
|
|
82
|
-
description_ja="
|
|
83
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
81
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None, fileio="in",
|
|
82
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
83
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
84
84
|
dict(opt="session_domain", type=Options.T_STR, default=None, required=False, multi=False, hide=True, choice=None,
|
|
85
85
|
description_ja="サインインしたユーザーのセッションが有効なドメインを指定します。",
|
|
86
86
|
description_en="Specify the domain for which the signed-in user's session is valid."),
|
|
@@ -93,12 +93,12 @@ class WebStart(feature.UnsupportEdgeFeature, agent_base.AgentBase):
|
|
|
93
93
|
dict(opt="session_timeout", type=Options.T_INT, default="900", required=False, multi=False, hide=True, choice=None,
|
|
94
94
|
description_ja="サインインしたユーザーのセッションタイムアウトの時間を秒で指定します。",
|
|
95
95
|
description_en="Specify the session timeout in seconds for signed-in users."),
|
|
96
|
-
dict(opt="
|
|
97
|
-
description_ja="
|
|
98
|
-
description_en="Specifies the number of
|
|
99
|
-
dict(opt="
|
|
100
|
-
description_ja="
|
|
101
|
-
description_en="Specify the timeout duration of the
|
|
96
|
+
dict(opt="gunicorn_workers", type=Options.T_INT, default=multiprocessing.cpu_count()*2, required=False, multi=False, hide=True, choice=None,
|
|
97
|
+
description_ja="gunicornワーカー数を指定します。Linux環境でのみ有効です。-1又は未指定の場合はCPU数の2倍を使用します。",
|
|
98
|
+
description_en="Specifies the number of gunicorn workers, valid only in Linux environment. If -1 or unspecified, twice the number of CPUs is used."),
|
|
99
|
+
dict(opt="gunicorn_timeout", type=Options.T_INT, default=30, required=False, multi=False, hide=True, choice=None,
|
|
100
|
+
description_ja="gunicornワーカーのタイムアウトの時間を秒で指定します。",
|
|
101
|
+
description_en="Specify the timeout duration of the gunicorn worker in seconds."),
|
|
102
102
|
dict(opt="client_only", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
103
103
|
description_ja="サーバーへの接続を行わないようにします。",
|
|
104
104
|
description_en="Do not make connections to the server."),
|
|
@@ -232,5 +232,5 @@ class WebStart(feature.UnsupportEdgeFeature, agent_base.AgentBase):
|
|
|
232
232
|
ssl_cert=args.ssl_cert, ssl_key=args.ssl_key, ssl_keypass=args.ssl_keypass, ssl_ca_certs=args.ssl_ca_certs,
|
|
233
233
|
session_domain=args.session_domain, session_path=args.session_path,
|
|
234
234
|
session_secure=args.session_secure, session_timeout=args.session_timeout,
|
|
235
|
-
outputs_key=args.outputs_key,
|
|
235
|
+
outputs_key=args.outputs_key, gunicorn_workers=args.gunicorn_workers, gunicorn_timeout=args.gunicorn_timeout,
|
|
236
236
|
agent_runner=agent_runner, mcp=mcp,)
|
|
@@ -55,9 +55,9 @@ class WebUserAdd(feature.UnsupportEdgeFeature):
|
|
|
55
55
|
dict(opt="user_group", type=Options.T_STR, default=None, required=True, multi=True, hide=False, choice=None,
|
|
56
56
|
description_ja="ユーザーが所属するグループを指定します。",
|
|
57
57
|
description_en="Specifies the groups to which the user belongs."),
|
|
58
|
-
dict(opt="signin_file", type=Options.T_FILE, default=
|
|
59
|
-
description_ja="
|
|
60
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
58
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=True, multi=False, hide=False, choice=None, fileio="in",
|
|
59
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
60
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
61
61
|
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
62
62
|
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
63
63
|
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
@@ -40,9 +40,9 @@ class WebUserDel(feature.UnsupportEdgeFeature):
|
|
|
40
40
|
dict(opt="user_id", type=Options.T_INT, default=None, required=True, multi=False, hide=False, choice=None,
|
|
41
41
|
description_ja="ユーザーIDを指定します。",
|
|
42
42
|
description_en="Specify the user ID."),
|
|
43
|
-
dict(opt="signin_file", type=Options.T_FILE, default=
|
|
44
|
-
description_ja="
|
|
45
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
43
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=True, multi=False, hide=False, choice=None, fileio="in",
|
|
44
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
45
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
46
46
|
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
47
47
|
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
48
48
|
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
@@ -55,9 +55,9 @@ class WebUserEdit(feature.UnsupportEdgeFeature):
|
|
|
55
55
|
dict(opt="user_group", type=Options.T_STR, default=None, required=True, multi=True, hide=False, choice=None,
|
|
56
56
|
description_ja="ユーザーが所属するグループを指定します。",
|
|
57
57
|
description_en="Specifies the groups to which the user belongs."),
|
|
58
|
-
dict(opt="signin_file", type=Options.T_FILE, default=
|
|
59
|
-
description_ja="
|
|
60
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
58
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=True, multi=False, hide=False, choice=None, fileio="in",
|
|
59
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
60
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
61
61
|
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
62
62
|
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
63
63
|
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
@@ -40,9 +40,9 @@ class WebUserList(feature.UnsupportEdgeFeature):
|
|
|
40
40
|
dict(opt="user_name", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
41
41
|
description_ja="ユーザー名を指定して取得します。省略した時は全てのユーザーを取得します。",
|
|
42
42
|
description_en="Retrieved by specifying a user name. If omitted, all users are retrieved."),
|
|
43
|
-
dict(opt="signin_file", type=Options.T_FILE, default=
|
|
44
|
-
description_ja="
|
|
45
|
-
description_en="Specify a file containing users and passwords with which they can signin.
|
|
43
|
+
dict(opt="signin_file", type=Options.T_FILE, default=None, required=True, multi=False, hide=False, choice=None, fileio="in",
|
|
44
|
+
description_ja=f"サインイン可能なユーザーとパスワードを記載したファイルを指定します。通常 '.{self.ver.__appid__}/user_list.yml' を指定します。",
|
|
45
|
+
description_en=f"Specify a file containing users and passwords with which they can signin.Typically, specify '.{self.ver.__appid__}/user_list.yml'."),
|
|
46
46
|
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
47
47
|
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
48
48
|
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
@@ -34,16 +34,14 @@ class ExecCmd(cmdbox_web_load_cmd.LoadCmd):
|
|
|
34
34
|
raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
|
|
35
35
|
opt = None
|
|
36
36
|
content_type = req.headers.get('content-type')
|
|
37
|
-
def _marge_opt(opt, param):
|
|
38
|
-
|
|
39
|
-
if k in param: opt[k] = param[k]
|
|
37
|
+
def _marge_opt(opt:Dict[str, Any], param:Dict[str, Any]) -> Dict[str, Any]:
|
|
38
|
+
opt.update(param)
|
|
40
39
|
return opt
|
|
40
|
+
opt_def = self.load_cmd(web, title)
|
|
41
41
|
if content_type is None:
|
|
42
|
-
opt =
|
|
43
|
-
opt = _marge_opt(opt, req.query_params)
|
|
42
|
+
opt = _marge_opt(opt_def, req.query_params)
|
|
44
43
|
elif content_type.startswith('multipart/form-data'):
|
|
45
|
-
opt =
|
|
46
|
-
opt = _marge_opt(opt, req.query_params)
|
|
44
|
+
opt = _marge_opt(opt_def, req.query_params)
|
|
47
45
|
form = await req.form()
|
|
48
46
|
#files = {key: value for key, value in form.multi_items() if isinstance(value, UploadFile)}
|
|
49
47
|
for key, fv in form.multi_items():
|
|
@@ -52,13 +50,12 @@ class ExecCmd(cmdbox_web_load_cmd.LoadCmd):
|
|
|
52
50
|
if key == 'input_file': opt['stdin'] = False
|
|
53
51
|
elif content_type.startswith('application/json'):
|
|
54
52
|
opt = await req.json()
|
|
53
|
+
opt = _marge_opt(opt_def, opt)
|
|
55
54
|
elif content_type.startswith('application/octet-stream'):
|
|
56
|
-
opt =
|
|
57
|
-
opt = _marge_opt(opt, req.query_params)
|
|
55
|
+
opt = _marge_opt(opt_def, req.query_params)
|
|
58
56
|
opt['_stdin_body'] = await req.body()
|
|
59
57
|
else:
|
|
60
|
-
opt =
|
|
61
|
-
opt = _marge_opt(opt, req.query_params)
|
|
58
|
+
opt = _marge_opt(opt_def, req.query_params)
|
|
62
59
|
if 'mode' not in opt or 'cmd' not in opt:
|
|
63
60
|
raise HTTPException(status_code=404, detail='mode or cmd is not found.')
|
|
64
61
|
opt['capture_stdout'] = nothread = True
|
|
@@ -147,9 +144,10 @@ class ExecCmd(cmdbox_web_load_cmd.LoadCmd):
|
|
|
147
144
|
if 'port' in opt: opt['port'] = web.redis_port
|
|
148
145
|
if 'password' in opt: opt['password'] = web.redis_password
|
|
149
146
|
if 'svname' in opt: opt['svname'] = web.svname
|
|
150
|
-
if
|
|
151
|
-
if '
|
|
152
|
-
|
|
147
|
+
if not 'clmsg_id' in opt: # optに含まれる場合は処理しない
|
|
148
|
+
if req.session is not None and 'signin' in req.session and req.session['signin'] is not None:
|
|
149
|
+
if 'clmsg_id' in req.session['signin'] and req.session['signin']['clmsg_id'] is not None:
|
|
150
|
+
opt['clmsg_id'] = req.session['signin']['clmsg_id']
|
|
153
151
|
ap.sv = None
|
|
154
152
|
ap.cl = None
|
|
155
153
|
ap.web = None
|
cmdbox/app/filer.py
CHANGED
|
@@ -206,13 +206,15 @@ class Filer(object):
|
|
|
206
206
|
try:
|
|
207
207
|
mime_type, encoding = mimetypes.guess_type(str(abspath))
|
|
208
208
|
fname = abspath.name
|
|
209
|
-
|
|
209
|
+
def _r(f):
|
|
210
210
|
fd = f.read()
|
|
211
211
|
if mime_type is not None and mime_type != 'image/svg+xml' and mime_type.startswith('image') and img_thumbnail > 0:
|
|
212
212
|
img = convert.imgbytes2thumbnail(fd, (img_thumbnail, img_thumbnail))
|
|
213
213
|
fd = convert.img2byte(img, "jpeg")
|
|
214
214
|
fname = f"{fname}.thumbnail.jpg"
|
|
215
215
|
data = convert.bytes2b64str(fd)
|
|
216
|
+
return data
|
|
217
|
+
data = common.load_file(abspath, _r, mode='rb')
|
|
216
218
|
return self.RESP_SUCCESS, dict(success=dict(name=fname, data=data, mime_type=mime_type))
|
|
217
219
|
except Exception as e:
|
|
218
220
|
self.logger.warning(f"Failed to download {abspath}. {e}")
|
|
@@ -252,8 +254,9 @@ class Filer(object):
|
|
|
252
254
|
try:
|
|
253
255
|
if mkdir:
|
|
254
256
|
save_path.parent.mkdir(parents=True, exist_ok=True)
|
|
255
|
-
|
|
257
|
+
def _w(f):
|
|
256
258
|
f.write(file_data)
|
|
259
|
+
common.save_file(Path(save_path), _w, mode='wb')
|
|
257
260
|
return self.RESP_SUCCESS, dict(success=f"Uploaded {save_path}")
|
|
258
261
|
except Exception as e:
|
|
259
262
|
self.logger.warning(f"Failed to upload {save_path}. {e}")
|
cmdbox/app/mcp.py
CHANGED
|
@@ -186,8 +186,9 @@ class Mcp:
|
|
|
186
186
|
if args.llmmodel is None: raise ValueError("llmmodel is required.")
|
|
187
187
|
if args.llmlocation is None: raise ValueError("llmlocation is required.")
|
|
188
188
|
if args.llmsvaccountfile is not None:
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
def _r(f):
|
|
190
|
+
return json.load(f)
|
|
191
|
+
vertex_credentials = common.load_file(Path(args.llmsvaccountfile), _r, mode='r')
|
|
191
192
|
elif args.llmprojectid is None: raise ValueError("llmprojectid is required.")
|
|
192
193
|
agent = Agent(
|
|
193
194
|
name=args.agent_name,
|
|
@@ -353,7 +354,7 @@ class Mcp:
|
|
|
353
354
|
func_txt += f' signin_data = signin.Signin.load_signin_file(args.signin_file)\n'
|
|
354
355
|
func_txt += f' req = scope["req"] if scope["req"] is not None else scope["websocket"]\n'
|
|
355
356
|
func_txt += f' sign = signin.Signin._check_signin(req, scope["res"], signin_data, logger)\n'
|
|
356
|
-
func_txt += f' if sign is not None:\n'
|
|
357
|
+
func_txt += f' if sign is not None or "signin" not in req.session or "groups" not in req.session["signin"]:\n'
|
|
357
358
|
func_txt += f' logger.warning("Unable to execute command because authentication information cannot be obtained")\n'
|
|
358
359
|
func_txt += f' return dict(warn="Unable to execute command because authentication information cannot be obtained")\n'
|
|
359
360
|
func_txt += f' groups = req.session["signin"]["groups"]\n'
|
cmdbox/app/options.py
CHANGED
|
@@ -267,6 +267,14 @@ class Options:
|
|
|
267
267
|
short="d", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
268
268
|
description_ja="デバックモードで起動します。",
|
|
269
269
|
description_en="Starts in debug mode.")
|
|
270
|
+
self._options["debug_attach"] = dict(
|
|
271
|
+
short="debug_attach", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
272
|
+
description_ja="デバックプロセスへのアタッチを有効にするかどうかを指定します。",
|
|
273
|
+
description_en="Specify whether to enable attaching to the debug process.")
|
|
274
|
+
self._options["debug_attach_port"] = dict(
|
|
275
|
+
short="debug_attach_port", type=Options.T_INT, default=5678, required=False, multi=False, hide=True, choice=None,
|
|
276
|
+
description_ja="デバックプロセスにアタッチするポート番号を指定します。",
|
|
277
|
+
description_en="Specify the port number to attach to the debug process.")
|
|
270
278
|
self._options["format"] = dict(
|
|
271
279
|
short="f", type=Options.T_BOOL, default=None, required=False, multi=False, hide=True,
|
|
272
280
|
description_ja="処理結果を見やすい形式で出力します。指定しない場合json形式で出力します。",
|
cmdbox/app/web.py
CHANGED
|
@@ -719,7 +719,7 @@ class Web:
|
|
|
719
719
|
def start(self, allow_host:str="0.0.0.0", listen_port:int=8081, ssl_listen_port:int=8443,
|
|
720
720
|
ssl_cert:Path=None, ssl_key:Path=None, ssl_keypass:str=None, ssl_ca_certs:Path=None,
|
|
721
721
|
session_domain:str=None, session_path:str='/', session_secure:bool=False, session_timeout:int=900, outputs_key:List[str]=[],
|
|
722
|
-
|
|
722
|
+
gunicorn_workers:int=-1, gunicorn_timeout:int=30,
|
|
723
723
|
agent_runner=None, mcp=None,):
|
|
724
724
|
"""
|
|
725
725
|
Webサーバを起動する
|
|
@@ -737,8 +737,8 @@ class Web:
|
|
|
737
737
|
session_secure (bool, optional): セッションセキュア. Defaults to False.
|
|
738
738
|
session_timeout (int, optional): セッションタイムアウト. Defaults to 900.
|
|
739
739
|
outputs_key (list, optional): 出力キー. Defaults to [].
|
|
740
|
-
|
|
741
|
-
|
|
740
|
+
gunicorn_workers (int, optional): Gunicornワーカー数. Defaults to -1.
|
|
741
|
+
gunicorn_timeout (int, optional): Gunicornタイムアウト. Defaults to 30.
|
|
742
742
|
agent_runner (Runner, optional): エージェントランナー. Defaults to None.
|
|
743
743
|
mcp (MCP, optional): MCP. Defaults to None.
|
|
744
744
|
"""
|
|
@@ -754,8 +754,8 @@ class Web:
|
|
|
754
754
|
self.session_path = session_path
|
|
755
755
|
self.session_secure = session_secure
|
|
756
756
|
self.session_timeout = session_timeout
|
|
757
|
-
self.
|
|
758
|
-
self.
|
|
757
|
+
self.gunicorn_workers = gunicorn_workers
|
|
758
|
+
self.gunicorn_timeout = gunicorn_timeout
|
|
759
759
|
self.agent_runner = agent_runner
|
|
760
760
|
self.mcp = mcp
|
|
761
761
|
if self.logger.level == logging.DEBUG:
|
|
@@ -771,8 +771,8 @@ class Web:
|
|
|
771
771
|
self.logger.debug(f"web start parameter: session_path={self.session_path}")
|
|
772
772
|
self.logger.debug(f"web start parameter: session_secure={self.session_secure}")
|
|
773
773
|
self.logger.debug(f"web start parameter: session_timeout={self.session_timeout}")
|
|
774
|
-
self.logger.debug(f"web start parameter:
|
|
775
|
-
self.logger.debug(f"web start parameter:
|
|
774
|
+
self.logger.debug(f"web start parameter: gunicorn_workers={self.gunicorn_workers}")
|
|
775
|
+
self.logger.debug(f"web start parameter: gunicorn_timeout={self.gunicorn_timeout}")
|
|
776
776
|
self.logger.debug(f"web start parameter: agent_runner={self.agent_runner}")
|
|
777
777
|
self.logger.debug(f"web start parameter: mcp={self.mcp}")
|
|
778
778
|
|
|
@@ -894,21 +894,22 @@ class Web:
|
|
|
894
894
|
https_config = Config(app=app, host=self.allow_host, port=self.ssl_listen_port,
|
|
895
895
|
ssl_certfile=self.ssl_cert, ssl_keyfile=self.ssl_key,
|
|
896
896
|
ssl_keyfile_password=self.ssl_keypass, ssl_ca_certs=self.ssl_ca_certs)
|
|
897
|
-
th_ssl =
|
|
898
|
-
|
|
897
|
+
th_ssl = ThreadedASGI(app, self.logger, config=https_config,
|
|
898
|
+
gunicorn_config=dict(workers=self.gunicorn_workers, timeout=self.gunicorn_timeout))
|
|
899
899
|
th_ssl.start()
|
|
900
900
|
browser_port = self.ssl_listen_port
|
|
901
901
|
else:
|
|
902
902
|
http_config = Config(app=app, host=self.allow_host, port=self.listen_port)
|
|
903
|
-
th =
|
|
904
|
-
|
|
903
|
+
th = ThreadedASGI(app, self.logger, config=http_config,
|
|
904
|
+
gunicorn_config=dict(workers=self.gunicorn_workers, timeout=self.gunicorn_timeout))
|
|
905
905
|
th.start()
|
|
906
906
|
browser_port = self.listen_port
|
|
907
907
|
try:
|
|
908
908
|
if self.gui_mode:
|
|
909
909
|
webbrowser.open(f'http://localhost:{browser_port}/gui')
|
|
910
|
-
|
|
910
|
+
def _w(f):
|
|
911
911
|
f.write(str(os.getpid()))
|
|
912
|
+
common.save_file("web.pid", _w)
|
|
912
913
|
while self.is_running:
|
|
913
914
|
gevent.sleep(1)
|
|
914
915
|
if th is not None:
|
|
@@ -926,35 +927,42 @@ class Web:
|
|
|
926
927
|
Webサーバを停止する
|
|
927
928
|
"""
|
|
928
929
|
try:
|
|
929
|
-
|
|
930
|
+
def _r(f):
|
|
930
931
|
pid = f.read()
|
|
931
932
|
if pid != "":
|
|
932
|
-
|
|
933
|
+
if platform.system() == "Windows":
|
|
934
|
+
os.system(f"taskkill /F /PID {pid}")
|
|
935
|
+
else:
|
|
936
|
+
os.kill(int(pid), signal.CTRL_C_EVENT)
|
|
933
937
|
self.logger.info(f"Stop web.")
|
|
934
938
|
else:
|
|
935
939
|
self.logger.warning(f"pid is empty.")
|
|
940
|
+
common.load_file("web.pid", _r)
|
|
936
941
|
Path("web.pid").unlink(missing_ok=True)
|
|
937
942
|
except:
|
|
938
943
|
traceback.print_exc()
|
|
939
944
|
finally:
|
|
940
945
|
self.logger.info(f"Exit web.")
|
|
941
946
|
|
|
942
|
-
class
|
|
943
|
-
def __init__(self, logger:logging.Logger, config:Config,
|
|
947
|
+
class ThreadedASGI:
|
|
948
|
+
def __init__(self, app:FastAPI, logger:logging.Logger, config:Config, gunicorn_config:Dict[str, Any]=None, force_single:bool=False):
|
|
949
|
+
self.app = app
|
|
944
950
|
self.logger = logger
|
|
945
|
-
self.
|
|
946
|
-
self.
|
|
951
|
+
self.config = config
|
|
952
|
+
self.gunicorn_config = gunicorn_config
|
|
953
|
+
# windows環境下ではシングルプロセスで動作させる
|
|
954
|
+
self.force_single = True if platform.system() == "Windows" else force_single
|
|
947
955
|
# loggerの設定
|
|
948
956
|
common.reset_logger("uvicorn")
|
|
949
957
|
common.reset_logger("uvicorn.error")
|
|
950
958
|
common.reset_logger("uvicorn.access")
|
|
951
959
|
#common.reset_logger("gunicorn.error")
|
|
952
960
|
#common.reset_logger("gunicorn.access")
|
|
953
|
-
if self.
|
|
961
|
+
if self.force_single:
|
|
962
|
+
config.ws = "wsproto"
|
|
954
963
|
self.server = uvicorn.Server(config)
|
|
955
964
|
self.thread = RaiseThread(daemon=True, target=self.server.run)
|
|
956
965
|
else:
|
|
957
|
-
|
|
958
966
|
from gunicorn.app.wsgiapp import WSGIApplication
|
|
959
967
|
class App(WSGIApplication):
|
|
960
968
|
def __init__(self, app, options):
|
|
@@ -969,29 +977,28 @@ class ThreadedUvicorn:
|
|
|
969
977
|
def load(self):
|
|
970
978
|
return self.application
|
|
971
979
|
opt = dict(bind=f"{config.host}:{config.port}",
|
|
972
|
-
worker_class="
|
|
980
|
+
worker_class="cmdbox.app.web.ASGIWorker",
|
|
973
981
|
access_log_format='[%(t)s] %(p)s %(l)s %(h)s "%(r)s" %(s)s',
|
|
974
982
|
loglevel=logging.getLevelName(self.logger.level),
|
|
975
983
|
keyfile=config.ssl_keyfile, certfile=config.ssl_certfile,
|
|
976
984
|
ca_certs=config.ssl_ca_certs, keyfile_password=config.ssl_keyfile_password,
|
|
977
985
|
limit_request_line=8190, limit_request_fields=100, limit_request_field_size=8190)
|
|
978
986
|
|
|
979
|
-
self.
|
|
980
|
-
if 'workers' not in self.
|
|
981
|
-
self.
|
|
982
|
-
if self.
|
|
983
|
-
self.
|
|
984
|
-
if 'timeout' not in self.
|
|
985
|
-
self.
|
|
986
|
-
if self.
|
|
987
|
-
self.
|
|
987
|
+
self.gunicorn_config = self.gunicorn_config or {}
|
|
988
|
+
if 'workers' not in self.gunicorn_config:
|
|
989
|
+
self.gunicorn_config['workers'] = None
|
|
990
|
+
if self.gunicorn_config['workers'] is None or self.gunicorn_config['workers'] <= 0:
|
|
991
|
+
self.gunicorn_config['workers'] = multiprocessing.cpu_count()*2
|
|
992
|
+
if 'timeout' not in self.gunicorn_config:
|
|
993
|
+
self.gunicorn_config['timeout'] = None
|
|
994
|
+
if self.gunicorn_config['timeout'] is None or self.gunicorn_config['timeout'] <= 0:
|
|
995
|
+
self.gunicorn_config['timeout'] = 30
|
|
988
996
|
|
|
989
|
-
opt = {**opt, **self.
|
|
990
|
-
self.server = App(
|
|
991
|
-
#self.thread = RaiseThread(daemon=True, target=self.server.run)
|
|
997
|
+
opt = {**opt, **self.gunicorn_config}
|
|
998
|
+
self.server = App(app, opt)
|
|
992
999
|
|
|
993
1000
|
def start(self):
|
|
994
|
-
if self.
|
|
1001
|
+
if self.force_single:
|
|
995
1002
|
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
|
996
1003
|
self.thread.start()
|
|
997
1004
|
asyncio.run(self.wait_for_started())
|
|
@@ -1005,7 +1012,7 @@ class ThreadedUvicorn:
|
|
|
1005
1012
|
await asyncio.sleep(0.1)
|
|
1006
1013
|
|
|
1007
1014
|
def stop(self):
|
|
1008
|
-
if self.
|
|
1015
|
+
if self.force_single:
|
|
1009
1016
|
if self.thread.is_alive():
|
|
1010
1017
|
self.server.should_exit = True
|
|
1011
1018
|
self.thread.raise_exception()
|
|
@@ -1015,7 +1022,7 @@ class ThreadedUvicorn:
|
|
|
1015
1022
|
self.server.started = False
|
|
1016
1023
|
|
|
1017
1024
|
def is_alive(self):
|
|
1018
|
-
if self.
|
|
1025
|
+
if self.force_single:
|
|
1019
1026
|
return self.thread.is_alive()
|
|
1020
1027
|
else:
|
|
1021
1028
|
return self.server.started
|
|
@@ -1044,3 +1051,10 @@ class RaiseThread(threading.Thread):
|
|
|
1044
1051
|
0
|
|
1045
1052
|
)
|
|
1046
1053
|
print('Failure in raising exception')
|
|
1054
|
+
|
|
1055
|
+
if platform.system() != "Windows":
|
|
1056
|
+
from uvicorn.workers import UvicornWorker
|
|
1057
|
+
class ASGIWorker(UvicornWorker):
|
|
1058
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
1059
|
+
super().__init__(*args, **kwargs)
|
|
1060
|
+
self.config.ws = "wsproto"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright P G Jones 2018.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
|
4
|
+
obtaining a copy of this software and associated documentation
|
|
5
|
+
files (the "Software"), to deal in the Software without
|
|
6
|
+
restriction, including without limitation the rights to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the
|
|
9
|
+
Software is furnished to do so, subject to the following
|
|
10
|
+
conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -3,7 +3,7 @@ Except when otherwise stated (look for LICENSE files in directories or
|
|
|
3
3
|
information at the beginning of each file) all software and
|
|
4
4
|
documentation is licensed as follows:
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
MIT No Attribution
|
|
7
7
|
|
|
8
8
|
Permission is hereby granted, free of charge, to any person
|
|
9
9
|
obtaining a copy of this software and associated documentation
|
|
@@ -11,10 +11,7 @@ documentation is licensed as follows:
|
|
|
11
11
|
restriction, including without limitation the rights to use,
|
|
12
12
|
copy, modify, merge, publish, distribute, sublicense, and/or
|
|
13
13
|
sell copies of the Software, and to permit persons to whom the
|
|
14
|
-
Software is furnished to do so
|
|
15
|
-
|
|
16
|
-
The above copyright notice and this permission notice shall be included
|
|
17
|
-
in all copies or substantial portions of the Software.
|
|
14
|
+
Software is furnished to do so.
|
|
18
15
|
|
|
19
16
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
20
17
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015-2020 Cory Benfield and contributors
|
|
2
4
|
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
6
|
of this software and associated documentation files (the "Software"), to deal
|
cmdbox/licenses/{LICENSE_jsonschema_4_25_0_UNKNOWN.txt → LICENSE_priority_2_0_0_MIT_License.txt}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c)
|
|
1
|
+
Copyright (c) 2015 Cory Benfield
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
16
16
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
17
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
18
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
THE SOFTWARE.
|
|
19
|
+
THE SOFTWARE.
|