Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. Β
See raw diff
- .gitattributes +4 -0
- last-000001.safetensors +3 -0
- last-000002.safetensors +3 -0
- last-000003.safetensors +3 -0
- last-000004.safetensors +3 -0
- last.safetensors +3 -0
- last_20240119-052517.json +122 -0
- last_20240119-052939.json +122 -0
- tutorial-env/bin/Activate.ps1 +247 -0
- tutorial-env/bin/activate +69 -0
- tutorial-env/bin/activate.csh +26 -0
- tutorial-env/bin/activate.fish +69 -0
- tutorial-env/bin/huggingface-cli +8 -0
- tutorial-env/bin/normalizer +8 -0
- tutorial-env/bin/pip +8 -0
- tutorial-env/bin/pip3 +8 -0
- tutorial-env/bin/pip3.10 +8 -0
- tutorial-env/bin/python +3 -0
- tutorial-env/bin/python3 +3 -0
- tutorial-env/bin/python3.10 +3 -0
- tutorial-env/bin/tqdm +8 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__init__.py +2 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/__init__.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/enum.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/exceptions.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/inquirer.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/resolver.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/separator.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/utils.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/validator.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__init__.py +15 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/__init__.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/complex.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/control.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/list.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/simple.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/complex.py +294 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/control.py +227 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/list.py +238 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/base/simple.py +378 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__init__.py +1 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/__init__.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/instruction.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/message.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/spinner.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/validation.cpython-310.pyc +0 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/instruction.py +38 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/message.py +42 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/spinner.py +108 -0
- tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/validation.py +60 -0
.gitattributes
CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
tutorial-env/bin/python filter=lfs diff=lfs merge=lfs -text
|
37 |
+
tutorial-env/bin/python3 filter=lfs diff=lfs merge=lfs -text
|
38 |
+
tutorial-env/bin/python3.10 filter=lfs diff=lfs merge=lfs -text
|
39 |
+
tutorial-env/lib/python3.10/site-packages/yaml/_yaml.cpython-310-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
last-000001.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:bc75c9e5e079cb6f87cdfe9f7eddc7a34317edd681df81eb61af9db107825748
|
3 |
+
size 57419740
|
last-000002.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:689b5735ca8159e21a71a7946d000b982d1e45b4f5f1123f8f1664abdcddfbde
|
3 |
+
size 57419740
|
last-000003.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ca5e618ee507b54bbc25cfbae698a64fee7e6b030b8ed57211075f919a2f3338
|
3 |
+
size 57419740
|
last-000004.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:215855b36f371534371de3ca8e4214e5e0e7e2a213e96326c63336f4da0a3e46
|
3 |
+
size 57419740
|
last.safetensors
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:a08607bd519df98e52a5ccf0a066bc05d8d6067986c768c46bdec8dafcfc1415
|
3 |
+
size 57419740
|
last_20240119-052517.json
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"LoRA_type": "Standard",
|
3 |
+
"LyCORIS_preset": "full",
|
4 |
+
"adaptive_noise_scale": 0,
|
5 |
+
"additional_parameters": "",
|
6 |
+
"block_alphas": "",
|
7 |
+
"block_dims": "",
|
8 |
+
"block_lr_zero_threshold": "",
|
9 |
+
"bucket_no_upscale": true,
|
10 |
+
"bucket_reso_steps": 64,
|
11 |
+
"cache_latents": true,
|
12 |
+
"cache_latents_to_disk": true,
|
13 |
+
"caption_dropout_every_n_epochs": 0.0,
|
14 |
+
"caption_dropout_rate": 0,
|
15 |
+
"caption_extension": "",
|
16 |
+
"clip_skip": "1",
|
17 |
+
"color_aug": false,
|
18 |
+
"constrain": 0.0,
|
19 |
+
"conv_alpha": 1,
|
20 |
+
"conv_block_alphas": "",
|
21 |
+
"conv_block_dims": "",
|
22 |
+
"conv_dim": 1,
|
23 |
+
"debiased_estimation_loss": false,
|
24 |
+
"decompose_both": false,
|
25 |
+
"dim_from_weights": false,
|
26 |
+
"down_lr_weight": "",
|
27 |
+
"enable_bucket": true,
|
28 |
+
"epoch": 5,
|
29 |
+
"factor": -1,
|
30 |
+
"flip_aug": false,
|
31 |
+
"full_bf16": false,
|
32 |
+
"full_fp16": false,
|
33 |
+
"gradient_accumulation_steps": "1",
|
34 |
+
"gradient_checkpointing": false,
|
35 |
+
"keep_tokens": "0",
|
36 |
+
"learning_rate": 0.0005,
|
37 |
+
"logging_dir": "/workspace/organized/watches/log",
|
38 |
+
"lora_network_weights": "",
|
39 |
+
"lr_scheduler": "cosine",
|
40 |
+
"lr_scheduler_args": "",
|
41 |
+
"lr_scheduler_num_cycles": "",
|
42 |
+
"lr_scheduler_power": "",
|
43 |
+
"lr_warmup": "10",
|
44 |
+
"max_bucket_reso": 2048,
|
45 |
+
"max_data_loader_n_workers": "0",
|
46 |
+
"max_grad_norm": 1,
|
47 |
+
"max_resolution": "1024,1024",
|
48 |
+
"max_timestep": 1000,
|
49 |
+
"max_token_length": "75",
|
50 |
+
"max_train_epochs": "",
|
51 |
+
"max_train_steps": "",
|
52 |
+
"mem_eff_attn": false,
|
53 |
+
"mid_lr_weight": "",
|
54 |
+
"min_bucket_reso": 256,
|
55 |
+
"min_snr_gamma": 0,
|
56 |
+
"min_timestep": 0,
|
57 |
+
"mixed_precision": "fp16",
|
58 |
+
"model_list": "stabilityai/stable-diffusion-xl-base-1.0",
|
59 |
+
"module_dropout": 0,
|
60 |
+
"multires_noise_discount": 0,
|
61 |
+
"multires_noise_iterations": 0,
|
62 |
+
"network_alpha": 1,
|
63 |
+
"network_dim": 8,
|
64 |
+
"network_dropout": 0,
|
65 |
+
"no_token_padding": false,
|
66 |
+
"noise_offset": 0,
|
67 |
+
"noise_offset_type": "Original",
|
68 |
+
"num_cpu_threads_per_process": 2,
|
69 |
+
"optimizer": "Adafactor",
|
70 |
+
"optimizer_args": "scale_parameter=False relative_step=False warmup_init=False",
|
71 |
+
"output_dir": "/workspace/organized/watches/model",
|
72 |
+
"output_name": "last",
|
73 |
+
"persistent_data_loader_workers": false,
|
74 |
+
"pretrained_model_name_or_path": "stabilityai/stable-diffusion-xl-base-1.0",
|
75 |
+
"prior_loss_weight": 1.0,
|
76 |
+
"random_crop": false,
|
77 |
+
"rank_dropout": 0,
|
78 |
+
"rank_dropout_scale": false,
|
79 |
+
"reg_data_dir": "",
|
80 |
+
"rescaled": false,
|
81 |
+
"resume": "",
|
82 |
+
"sample_every_n_epochs": 0,
|
83 |
+
"sample_every_n_steps": 0,
|
84 |
+
"sample_prompts": "",
|
85 |
+
"sample_sampler": "euler_a",
|
86 |
+
"save_every_n_epochs": 1,
|
87 |
+
"save_every_n_steps": 0,
|
88 |
+
"save_last_n_steps": 0,
|
89 |
+
"save_last_n_steps_state": 0,
|
90 |
+
"save_model_as": "safetensors",
|
91 |
+
"save_precision": "fp16",
|
92 |
+
"save_state": false,
|
93 |
+
"scale_v_pred_loss_like_noise_pred": false,
|
94 |
+
"scale_weight_norms": 0,
|
95 |
+
"sdxl": true,
|
96 |
+
"sdxl_cache_text_encoder_outputs": false,
|
97 |
+
"sdxl_no_half_vae": true,
|
98 |
+
"seed": "",
|
99 |
+
"shuffle_caption": false,
|
100 |
+
"stop_text_encoder_training_pct": 0,
|
101 |
+
"text_encoder_lr": 5e-05,
|
102 |
+
"train_batch_size": 1,
|
103 |
+
"train_data_dir": "/workspace/organized/watches/img",
|
104 |
+
"train_norm": false,
|
105 |
+
"train_on_input": true,
|
106 |
+
"training_comment": "",
|
107 |
+
"unet_lr": 0.0001,
|
108 |
+
"unit": 1,
|
109 |
+
"up_lr_weight": "",
|
110 |
+
"use_cp": false,
|
111 |
+
"use_scalar": false,
|
112 |
+
"use_tucker": false,
|
113 |
+
"use_wandb": false,
|
114 |
+
"v2": false,
|
115 |
+
"v_parameterization": false,
|
116 |
+
"v_pred_like_loss": 0,
|
117 |
+
"vae": "",
|
118 |
+
"vae_batch_size": 0,
|
119 |
+
"wandb_api_key": "",
|
120 |
+
"weighted_captions": false,
|
121 |
+
"xformers": "xformers"
|
122 |
+
}
|
last_20240119-052939.json
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"LoRA_type": "Standard",
|
3 |
+
"LyCORIS_preset": "full",
|
4 |
+
"adaptive_noise_scale": 0,
|
5 |
+
"additional_parameters": "",
|
6 |
+
"block_alphas": "",
|
7 |
+
"block_dims": "",
|
8 |
+
"block_lr_zero_threshold": "",
|
9 |
+
"bucket_no_upscale": true,
|
10 |
+
"bucket_reso_steps": 64,
|
11 |
+
"cache_latents": true,
|
12 |
+
"cache_latents_to_disk": true,
|
13 |
+
"caption_dropout_every_n_epochs": 0.0,
|
14 |
+
"caption_dropout_rate": 0,
|
15 |
+
"caption_extension": "",
|
16 |
+
"clip_skip": "1",
|
17 |
+
"color_aug": false,
|
18 |
+
"constrain": 0.0,
|
19 |
+
"conv_alpha": 1,
|
20 |
+
"conv_block_alphas": "",
|
21 |
+
"conv_block_dims": "",
|
22 |
+
"conv_dim": 1,
|
23 |
+
"debiased_estimation_loss": false,
|
24 |
+
"decompose_both": false,
|
25 |
+
"dim_from_weights": false,
|
26 |
+
"down_lr_weight": "",
|
27 |
+
"enable_bucket": true,
|
28 |
+
"epoch": 5,
|
29 |
+
"factor": -1,
|
30 |
+
"flip_aug": false,
|
31 |
+
"full_bf16": false,
|
32 |
+
"full_fp16": false,
|
33 |
+
"gradient_accumulation_steps": "1",
|
34 |
+
"gradient_checkpointing": false,
|
35 |
+
"keep_tokens": "0",
|
36 |
+
"learning_rate": 0.0005,
|
37 |
+
"logging_dir": "/workspace/organized/watches/log",
|
38 |
+
"lora_network_weights": "",
|
39 |
+
"lr_scheduler": "cosine",
|
40 |
+
"lr_scheduler_args": "",
|
41 |
+
"lr_scheduler_num_cycles": "",
|
42 |
+
"lr_scheduler_power": "",
|
43 |
+
"lr_warmup": 10,
|
44 |
+
"max_bucket_reso": 2048,
|
45 |
+
"max_data_loader_n_workers": "0",
|
46 |
+
"max_grad_norm": 1,
|
47 |
+
"max_resolution": "1024,1024",
|
48 |
+
"max_timestep": 1000,
|
49 |
+
"max_token_length": "75",
|
50 |
+
"max_train_epochs": "",
|
51 |
+
"max_train_steps": "",
|
52 |
+
"mem_eff_attn": false,
|
53 |
+
"mid_lr_weight": "",
|
54 |
+
"min_bucket_reso": 256,
|
55 |
+
"min_snr_gamma": 0,
|
56 |
+
"min_timestep": 0,
|
57 |
+
"mixed_precision": "fp16",
|
58 |
+
"model_list": "stabilityai/stable-diffusion-xl-base-1.0",
|
59 |
+
"module_dropout": 0,
|
60 |
+
"multires_noise_discount": 0,
|
61 |
+
"multires_noise_iterations": 0,
|
62 |
+
"network_alpha": 1,
|
63 |
+
"network_dim": 8,
|
64 |
+
"network_dropout": 0,
|
65 |
+
"no_token_padding": false,
|
66 |
+
"noise_offset": 0,
|
67 |
+
"noise_offset_type": "Original",
|
68 |
+
"num_cpu_threads_per_process": 2,
|
69 |
+
"optimizer": "Adafactor",
|
70 |
+
"optimizer_args": "scale_parameter=False relative_step=False warmup_init=False",
|
71 |
+
"output_dir": "/workspace/organized/watches/model",
|
72 |
+
"output_name": "last",
|
73 |
+
"persistent_data_loader_workers": false,
|
74 |
+
"pretrained_model_name_or_path": "stabilityai/stable-diffusion-xl-base-1.0",
|
75 |
+
"prior_loss_weight": 1.0,
|
76 |
+
"random_crop": false,
|
77 |
+
"rank_dropout": 0,
|
78 |
+
"rank_dropout_scale": false,
|
79 |
+
"reg_data_dir": "",
|
80 |
+
"rescaled": false,
|
81 |
+
"resume": "",
|
82 |
+
"sample_every_n_epochs": 0,
|
83 |
+
"sample_every_n_steps": 0,
|
84 |
+
"sample_prompts": "",
|
85 |
+
"sample_sampler": "euler_a",
|
86 |
+
"save_every_n_epochs": 1,
|
87 |
+
"save_every_n_steps": 0,
|
88 |
+
"save_last_n_steps": 0,
|
89 |
+
"save_last_n_steps_state": 0,
|
90 |
+
"save_model_as": "safetensors",
|
91 |
+
"save_precision": "fp16",
|
92 |
+
"save_state": false,
|
93 |
+
"scale_v_pred_loss_like_noise_pred": false,
|
94 |
+
"scale_weight_norms": 0,
|
95 |
+
"sdxl": true,
|
96 |
+
"sdxl_cache_text_encoder_outputs": false,
|
97 |
+
"sdxl_no_half_vae": true,
|
98 |
+
"seed": "",
|
99 |
+
"shuffle_caption": false,
|
100 |
+
"stop_text_encoder_training_pct": 0,
|
101 |
+
"text_encoder_lr": 5e-05,
|
102 |
+
"train_batch_size": 1,
|
103 |
+
"train_data_dir": "/workspace/organized/watches/img",
|
104 |
+
"train_norm": false,
|
105 |
+
"train_on_input": true,
|
106 |
+
"training_comment": "",
|
107 |
+
"unet_lr": 0.0001,
|
108 |
+
"unit": 1,
|
109 |
+
"up_lr_weight": "",
|
110 |
+
"use_cp": false,
|
111 |
+
"use_scalar": false,
|
112 |
+
"use_tucker": false,
|
113 |
+
"use_wandb": false,
|
114 |
+
"v2": false,
|
115 |
+
"v_parameterization": false,
|
116 |
+
"v_pred_like_loss": 0,
|
117 |
+
"vae": "",
|
118 |
+
"vae_batch_size": 0,
|
119 |
+
"wandb_api_key": "",
|
120 |
+
"weighted_captions": false,
|
121 |
+
"xformers": "xformers"
|
122 |
+
}
|
tutorial-env/bin/Activate.ps1
ADDED
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<#
|
2 |
+
.Synopsis
|
3 |
+
Activate a Python virtual environment for the current PowerShell session.
|
4 |
+
|
5 |
+
.Description
|
6 |
+
Pushes the python executable for a virtual environment to the front of the
|
7 |
+
$Env:PATH environment variable and sets the prompt to signify that you are
|
8 |
+
in a Python virtual environment. Makes use of the command line switches as
|
9 |
+
well as the `pyvenv.cfg` file values present in the virtual environment.
|
10 |
+
|
11 |
+
.Parameter VenvDir
|
12 |
+
Path to the directory that contains the virtual environment to activate. The
|
13 |
+
default value for this is the parent of the directory that the Activate.ps1
|
14 |
+
script is located within.
|
15 |
+
|
16 |
+
.Parameter Prompt
|
17 |
+
The prompt prefix to display when this virtual environment is activated. By
|
18 |
+
default, this prompt is the name of the virtual environment folder (VenvDir)
|
19 |
+
surrounded by parentheses and followed by a single space (ie. '(.venv) ').
|
20 |
+
|
21 |
+
.Example
|
22 |
+
Activate.ps1
|
23 |
+
Activates the Python virtual environment that contains the Activate.ps1 script.
|
24 |
+
|
25 |
+
.Example
|
26 |
+
Activate.ps1 -Verbose
|
27 |
+
Activates the Python virtual environment that contains the Activate.ps1 script,
|
28 |
+
and shows extra information about the activation as it executes.
|
29 |
+
|
30 |
+
.Example
|
31 |
+
Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
|
32 |
+
Activates the Python virtual environment located in the specified location.
|
33 |
+
|
34 |
+
.Example
|
35 |
+
Activate.ps1 -Prompt "MyPython"
|
36 |
+
Activates the Python virtual environment that contains the Activate.ps1 script,
|
37 |
+
and prefixes the current prompt with the specified string (surrounded in
|
38 |
+
parentheses) while the virtual environment is active.
|
39 |
+
|
40 |
+
.Notes
|
41 |
+
On Windows, it may be required to enable this Activate.ps1 script by setting the
|
42 |
+
execution policy for the user. You can do this by issuing the following PowerShell
|
43 |
+
command:
|
44 |
+
|
45 |
+
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
46 |
+
|
47 |
+
For more information on Execution Policies:
|
48 |
+
https://go.microsoft.com/fwlink/?LinkID=135170
|
49 |
+
|
50 |
+
#>
|
51 |
+
Param(
|
52 |
+
[Parameter(Mandatory = $false)]
|
53 |
+
[String]
|
54 |
+
$VenvDir,
|
55 |
+
[Parameter(Mandatory = $false)]
|
56 |
+
[String]
|
57 |
+
$Prompt
|
58 |
+
)
|
59 |
+
|
60 |
+
<# Function declarations --------------------------------------------------- #>
|
61 |
+
|
62 |
+
<#
|
63 |
+
.Synopsis
|
64 |
+
Remove all shell session elements added by the Activate script, including the
|
65 |
+
addition of the virtual environment's Python executable from the beginning of
|
66 |
+
the PATH variable.
|
67 |
+
|
68 |
+
.Parameter NonDestructive
|
69 |
+
If present, do not remove this function from the global namespace for the
|
70 |
+
session.
|
71 |
+
|
72 |
+
#>
|
73 |
+
function global:deactivate ([switch]$NonDestructive) {
|
74 |
+
# Revert to original values
|
75 |
+
|
76 |
+
# The prior prompt:
|
77 |
+
if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
|
78 |
+
Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
|
79 |
+
Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
|
80 |
+
}
|
81 |
+
|
82 |
+
# The prior PYTHONHOME:
|
83 |
+
if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
|
84 |
+
Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
|
85 |
+
Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
|
86 |
+
}
|
87 |
+
|
88 |
+
# The prior PATH:
|
89 |
+
if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
|
90 |
+
Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
|
91 |
+
Remove-Item -Path Env:_OLD_VIRTUAL_PATH
|
92 |
+
}
|
93 |
+
|
94 |
+
# Just remove the VIRTUAL_ENV altogether:
|
95 |
+
if (Test-Path -Path Env:VIRTUAL_ENV) {
|
96 |
+
Remove-Item -Path env:VIRTUAL_ENV
|
97 |
+
}
|
98 |
+
|
99 |
+
# Just remove VIRTUAL_ENV_PROMPT altogether.
|
100 |
+
if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
|
101 |
+
Remove-Item -Path env:VIRTUAL_ENV_PROMPT
|
102 |
+
}
|
103 |
+
|
104 |
+
# Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
|
105 |
+
if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
|
106 |
+
Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
|
107 |
+
}
|
108 |
+
|
109 |
+
# Leave deactivate function in the global namespace if requested:
|
110 |
+
if (-not $NonDestructive) {
|
111 |
+
Remove-Item -Path function:deactivate
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
<#
|
116 |
+
.Description
|
117 |
+
Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
|
118 |
+
given folder, and returns them in a map.
|
119 |
+
|
120 |
+
For each line in the pyvenv.cfg file, if that line can be parsed into exactly
|
121 |
+
two strings separated by `=` (with any amount of whitespace surrounding the =)
|
122 |
+
then it is considered a `key = value` line. The left hand string is the key,
|
123 |
+
the right hand is the value.
|
124 |
+
|
125 |
+
If the value starts with a `'` or a `"` then the first and last character is
|
126 |
+
stripped from the value before being captured.
|
127 |
+
|
128 |
+
.Parameter ConfigDir
|
129 |
+
Path to the directory that contains the `pyvenv.cfg` file.
|
130 |
+
#>
|
131 |
+
function Get-PyVenvConfig(
|
132 |
+
[String]
|
133 |
+
$ConfigDir
|
134 |
+
) {
|
135 |
+
Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
|
136 |
+
|
137 |
+
# Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
|
138 |
+
$pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
|
139 |
+
|
140 |
+
# An empty map will be returned if no config file is found.
|
141 |
+
$pyvenvConfig = @{ }
|
142 |
+
|
143 |
+
if ($pyvenvConfigPath) {
|
144 |
+
|
145 |
+
Write-Verbose "File exists, parse `key = value` lines"
|
146 |
+
$pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
|
147 |
+
|
148 |
+
$pyvenvConfigContent | ForEach-Object {
|
149 |
+
$keyval = $PSItem -split "\s*=\s*", 2
|
150 |
+
if ($keyval[0] -and $keyval[1]) {
|
151 |
+
$val = $keyval[1]
|
152 |
+
|
153 |
+
# Remove extraneous quotations around a string value.
|
154 |
+
if ("'""".Contains($val.Substring(0, 1))) {
|
155 |
+
$val = $val.Substring(1, $val.Length - 2)
|
156 |
+
}
|
157 |
+
|
158 |
+
$pyvenvConfig[$keyval[0]] = $val
|
159 |
+
Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
|
160 |
+
}
|
161 |
+
}
|
162 |
+
}
|
163 |
+
return $pyvenvConfig
|
164 |
+
}
|
165 |
+
|
166 |
+
|
167 |
+
<# Begin Activate script --------------------------------------------------- #>
|
168 |
+
|
169 |
+
# Determine the containing directory of this script
|
170 |
+
$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
171 |
+
$VenvExecDir = Get-Item -Path $VenvExecPath
|
172 |
+
|
173 |
+
Write-Verbose "Activation script is located in path: '$VenvExecPath'"
|
174 |
+
Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
|
175 |
+
Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
|
176 |
+
|
177 |
+
# Set values required in priority: CmdLine, ConfigFile, Default
|
178 |
+
# First, get the location of the virtual environment, it might not be
|
179 |
+
# VenvExecDir if specified on the command line.
|
180 |
+
if ($VenvDir) {
|
181 |
+
Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
|
182 |
+
}
|
183 |
+
else {
|
184 |
+
Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
|
185 |
+
$VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
|
186 |
+
Write-Verbose "VenvDir=$VenvDir"
|
187 |
+
}
|
188 |
+
|
189 |
+
# Next, read the `pyvenv.cfg` file to determine any required value such
|
190 |
+
# as `prompt`.
|
191 |
+
$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
|
192 |
+
|
193 |
+
# Next, set the prompt from the command line, or the config file, or
|
194 |
+
# just use the name of the virtual environment folder.
|
195 |
+
if ($Prompt) {
|
196 |
+
Write-Verbose "Prompt specified as argument, using '$Prompt'"
|
197 |
+
}
|
198 |
+
else {
|
199 |
+
Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
|
200 |
+
if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
|
201 |
+
Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
|
202 |
+
$Prompt = $pyvenvCfg['prompt'];
|
203 |
+
}
|
204 |
+
else {
|
205 |
+
Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
|
206 |
+
Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
|
207 |
+
$Prompt = Split-Path -Path $venvDir -Leaf
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
Write-Verbose "Prompt = '$Prompt'"
|
212 |
+
Write-Verbose "VenvDir='$VenvDir'"
|
213 |
+
|
214 |
+
# Deactivate any currently active virtual environment, but leave the
|
215 |
+
# deactivate function in place.
|
216 |
+
deactivate -nondestructive
|
217 |
+
|
218 |
+
# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
|
219 |
+
# that there is an activated venv.
|
220 |
+
$env:VIRTUAL_ENV = $VenvDir
|
221 |
+
|
222 |
+
if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
|
223 |
+
|
224 |
+
Write-Verbose "Setting prompt to '$Prompt'"
|
225 |
+
|
226 |
+
# Set the prompt to include the env name
|
227 |
+
# Make sure _OLD_VIRTUAL_PROMPT is global
|
228 |
+
function global:_OLD_VIRTUAL_PROMPT { "" }
|
229 |
+
Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
|
230 |
+
New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
|
231 |
+
|
232 |
+
function global:prompt {
|
233 |
+
Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
|
234 |
+
_OLD_VIRTUAL_PROMPT
|
235 |
+
}
|
236 |
+
$env:VIRTUAL_ENV_PROMPT = $Prompt
|
237 |
+
}
|
238 |
+
|
239 |
+
# Clear PYTHONHOME
|
240 |
+
if (Test-Path -Path Env:PYTHONHOME) {
|
241 |
+
Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
|
242 |
+
Remove-Item -Path Env:PYTHONHOME
|
243 |
+
}
|
244 |
+
|
245 |
+
# Add the venv to the PATH
|
246 |
+
Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
|
247 |
+
$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
|
tutorial-env/bin/activate
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This file must be used with "source bin/activate" *from bash*
|
2 |
+
# you cannot run it directly
|
3 |
+
|
4 |
+
deactivate () {
|
5 |
+
# reset old environment variables
|
6 |
+
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
|
7 |
+
PATH="${_OLD_VIRTUAL_PATH:-}"
|
8 |
+
export PATH
|
9 |
+
unset _OLD_VIRTUAL_PATH
|
10 |
+
fi
|
11 |
+
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
|
12 |
+
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
|
13 |
+
export PYTHONHOME
|
14 |
+
unset _OLD_VIRTUAL_PYTHONHOME
|
15 |
+
fi
|
16 |
+
|
17 |
+
# This should detect bash and zsh, which have a hash command that must
|
18 |
+
# be called to get it to forget past commands. Without forgetting
|
19 |
+
# past commands the $PATH changes we made may not be respected
|
20 |
+
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
|
21 |
+
hash -r 2> /dev/null
|
22 |
+
fi
|
23 |
+
|
24 |
+
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
25 |
+
PS1="${_OLD_VIRTUAL_PS1:-}"
|
26 |
+
export PS1
|
27 |
+
unset _OLD_VIRTUAL_PS1
|
28 |
+
fi
|
29 |
+
|
30 |
+
unset VIRTUAL_ENV
|
31 |
+
unset VIRTUAL_ENV_PROMPT
|
32 |
+
if [ ! "${1:-}" = "nondestructive" ] ; then
|
33 |
+
# Self destruct!
|
34 |
+
unset -f deactivate
|
35 |
+
fi
|
36 |
+
}
|
37 |
+
|
38 |
+
# unset irrelevant variables
|
39 |
+
deactivate nondestructive
|
40 |
+
|
41 |
+
VIRTUAL_ENV="/workspace/organized/watches/model/tutorial-env"
|
42 |
+
export VIRTUAL_ENV
|
43 |
+
|
44 |
+
_OLD_VIRTUAL_PATH="$PATH"
|
45 |
+
PATH="$VIRTUAL_ENV/bin:$PATH"
|
46 |
+
export PATH
|
47 |
+
|
48 |
+
# unset PYTHONHOME if set
|
49 |
+
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
50 |
+
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
51 |
+
if [ -n "${PYTHONHOME:-}" ] ; then
|
52 |
+
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
53 |
+
unset PYTHONHOME
|
54 |
+
fi
|
55 |
+
|
56 |
+
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
57 |
+
_OLD_VIRTUAL_PS1="${PS1:-}"
|
58 |
+
PS1="(tutorial-env) ${PS1:-}"
|
59 |
+
export PS1
|
60 |
+
VIRTUAL_ENV_PROMPT="(tutorial-env) "
|
61 |
+
export VIRTUAL_ENV_PROMPT
|
62 |
+
fi
|
63 |
+
|
64 |
+
# This should detect bash and zsh, which have a hash command that must
|
65 |
+
# be called to get it to forget past commands. Without forgetting
|
66 |
+
# past commands the $PATH changes we made may not be respected
|
67 |
+
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
|
68 |
+
hash -r 2> /dev/null
|
69 |
+
fi
|
tutorial-env/bin/activate.csh
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This file must be used with "source bin/activate.csh" *from csh*.
|
2 |
+
# You cannot run it directly.
|
3 |
+
# Created by Davide Di Blasi <davidedb@gmail.com>.
|
4 |
+
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
|
5 |
+
|
6 |
+
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
|
7 |
+
|
8 |
+
# Unset irrelevant variables.
|
9 |
+
deactivate nondestructive
|
10 |
+
|
11 |
+
setenv VIRTUAL_ENV "/workspace/organized/watches/model/tutorial-env"
|
12 |
+
|
13 |
+
set _OLD_VIRTUAL_PATH="$PATH"
|
14 |
+
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
|
15 |
+
|
16 |
+
|
17 |
+
set _OLD_VIRTUAL_PROMPT="$prompt"
|
18 |
+
|
19 |
+
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
20 |
+
set prompt = "(tutorial-env) $prompt"
|
21 |
+
setenv VIRTUAL_ENV_PROMPT "(tutorial-env) "
|
22 |
+
endif
|
23 |
+
|
24 |
+
alias pydoc python -m pydoc
|
25 |
+
|
26 |
+
rehash
|
tutorial-env/bin/activate.fish
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This file must be used with "source <venv>/bin/activate.fish" *from fish*
|
2 |
+
# (https://fishshell.com/); you cannot run it directly.
|
3 |
+
|
4 |
+
function deactivate -d "Exit virtual environment and return to normal shell environment"
|
5 |
+
# reset old environment variables
|
6 |
+
if test -n "$_OLD_VIRTUAL_PATH"
|
7 |
+
set -gx PATH $_OLD_VIRTUAL_PATH
|
8 |
+
set -e _OLD_VIRTUAL_PATH
|
9 |
+
end
|
10 |
+
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
|
11 |
+
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
|
12 |
+
set -e _OLD_VIRTUAL_PYTHONHOME
|
13 |
+
end
|
14 |
+
|
15 |
+
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
16 |
+
set -e _OLD_FISH_PROMPT_OVERRIDE
|
17 |
+
# prevents error when using nested fish instances (Issue #93858)
|
18 |
+
if functions -q _old_fish_prompt
|
19 |
+
functions -e fish_prompt
|
20 |
+
functions -c _old_fish_prompt fish_prompt
|
21 |
+
functions -e _old_fish_prompt
|
22 |
+
end
|
23 |
+
end
|
24 |
+
|
25 |
+
set -e VIRTUAL_ENV
|
26 |
+
set -e VIRTUAL_ENV_PROMPT
|
27 |
+
if test "$argv[1]" != "nondestructive"
|
28 |
+
# Self-destruct!
|
29 |
+
functions -e deactivate
|
30 |
+
end
|
31 |
+
end
|
32 |
+
|
33 |
+
# Unset irrelevant variables.
|
34 |
+
deactivate nondestructive
|
35 |
+
|
36 |
+
set -gx VIRTUAL_ENV "/workspace/organized/watches/model/tutorial-env"
|
37 |
+
|
38 |
+
set -gx _OLD_VIRTUAL_PATH $PATH
|
39 |
+
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
|
40 |
+
|
41 |
+
# Unset PYTHONHOME if set.
|
42 |
+
if set -q PYTHONHOME
|
43 |
+
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
|
44 |
+
set -e PYTHONHOME
|
45 |
+
end
|
46 |
+
|
47 |
+
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
|
48 |
+
# fish uses a function instead of an env var to generate the prompt.
|
49 |
+
|
50 |
+
# Save the current fish_prompt function as the function _old_fish_prompt.
|
51 |
+
functions -c fish_prompt _old_fish_prompt
|
52 |
+
|
53 |
+
# With the original prompt function renamed, we can override with our own.
|
54 |
+
function fish_prompt
|
55 |
+
# Save the return status of the last command.
|
56 |
+
set -l old_status $status
|
57 |
+
|
58 |
+
# Output the venv prompt; color taken from the blue of the Python logo.
|
59 |
+
printf "%s%s%s" (set_color 4B8BBE) "(tutorial-env) " (set_color normal)
|
60 |
+
|
61 |
+
# Restore the return status of the previous command.
|
62 |
+
echo "exit $old_status" | .
|
63 |
+
# Output the original/"old" prompt.
|
64 |
+
_old_fish_prompt
|
65 |
+
end
|
66 |
+
|
67 |
+
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
|
68 |
+
set -gx VIRTUAL_ENV_PROMPT "(tutorial-env) "
|
69 |
+
end
|
tutorial-env/bin/huggingface-cli
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/workspace/organized/watches/model/tutorial-env/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from huggingface_hub.commands.huggingface_cli import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
tutorial-env/bin/normalizer
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/workspace/organized/watches/model/tutorial-env/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from charset_normalizer.cli import cli_detect
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(cli_detect())
|
tutorial-env/bin/pip
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/workspace/organized/watches/model/tutorial-env/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from pip._internal.cli.main import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
tutorial-env/bin/pip3
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/workspace/organized/watches/model/tutorial-env/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from pip._internal.cli.main import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
tutorial-env/bin/pip3.10
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/workspace/organized/watches/model/tutorial-env/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from pip._internal.cli.main import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
tutorial-env/bin/python
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:45692c3da2492563eabf0a8f5dc18d20dc9c34ffe3a18202563e00bae684be91
|
3 |
+
size 5904904
|
tutorial-env/bin/python3
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:45692c3da2492563eabf0a8f5dc18d20dc9c34ffe3a18202563e00bae684be91
|
3 |
+
size 5904904
|
tutorial-env/bin/python3.10
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:45692c3da2492563eabf0a8f5dc18d20dc9c34ffe3a18202563e00bae684be91
|
3 |
+
size 5904904
|
tutorial-env/bin/tqdm
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/workspace/organized/watches/model/tutorial-env/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from tqdm.cli import main
|
6 |
+
if __name__ == '__main__':
|
7 |
+
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
8 |
+
sys.exit(main())
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__init__.py
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
from InquirerPy.resolver import prompt, prompt_async
|
2 |
+
from InquirerPy.utils import get_style
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (315 Bytes). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/enum.cpython-310.pyc
ADDED
Binary file (533 Bytes). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/exceptions.cpython-310.pyc
ADDED
Binary file (1.21 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/inquirer.cpython-310.pyc
ADDED
Binary file (915 Bytes). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/resolver.cpython-310.pyc
ADDED
Binary file (7 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/separator.cpython-310.pyc
ADDED
Binary file (1.2 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/utils.cpython-310.pyc
ADDED
Binary file (9.29 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/__pycache__/validator.cpython-310.pyc
ADDED
Binary file (6.12 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__init__.py
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Module contains base class for prompts.
|
2 |
+
|
3 |
+
BaseSimplePrompt β InputPrompt β SecretPrompt ...
|
4 |
+
β
|
5 |
+
BaseComplexPrompt
|
6 |
+
β
|
7 |
+
BaseListPrompt β FuzzyPrompt
|
8 |
+
β
|
9 |
+
ListPrompt β ExpandPrompt ...
|
10 |
+
"""
|
11 |
+
|
12 |
+
from .complex import BaseComplexPrompt, FakeDocument
|
13 |
+
from .control import Choice, InquirerPyUIListControl
|
14 |
+
from .list import BaseListPrompt
|
15 |
+
from .simple import BaseSimplePrompt
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (663 Bytes). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/complex.cpython-310.pyc
ADDED
Binary file (10.7 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/control.cpython-310.pyc
ADDED
Binary file (7.76 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/list.cpython-310.pyc
ADDED
Binary file (6.97 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/__pycache__/simple.cpython-310.pyc
ADDED
Binary file (12.9 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/complex.py
ADDED
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Contains the interface class :class:`.BaseComplexPrompt` for more complex prompts and the mocked document class :class:`.FakeDocument`."""
|
2 |
+
import shutil
|
3 |
+
from dataclasses import dataclass
|
4 |
+
from typing import Any, Callable, List, Optional, Tuple, Union
|
5 |
+
|
6 |
+
from prompt_toolkit.application import Application
|
7 |
+
from prompt_toolkit.enums import EditingMode
|
8 |
+
from prompt_toolkit.filters.base import Condition, FilterOrBool
|
9 |
+
from prompt_toolkit.key_binding.key_bindings import KeyHandlerCallable
|
10 |
+
from prompt_toolkit.keys import Keys
|
11 |
+
|
12 |
+
from InquirerPy.base.simple import BaseSimplePrompt
|
13 |
+
from InquirerPy.enum import INQUIRERPY_KEYBOARD_INTERRUPT
|
14 |
+
from InquirerPy.utils import (
|
15 |
+
InquirerPySessionResult,
|
16 |
+
InquirerPyStyle,
|
17 |
+
InquirerPyValidate,
|
18 |
+
)
|
19 |
+
|
20 |
+
|
21 |
+
@dataclass
|
22 |
+
class FakeDocument:
|
23 |
+
"""A fake `prompt_toolkit` document class.
|
24 |
+
|
25 |
+
Work around to allow non-buffer type :class:`~prompt_toolkit.layout.UIControl` to use
|
26 |
+
:class:`~prompt_toolkit.validation.Validator`.
|
27 |
+
|
28 |
+
Args:
|
29 |
+
text: Content to be validated.
|
30 |
+
cursor_position: Fake cursor position.
|
31 |
+
"""
|
32 |
+
|
33 |
+
text: str
|
34 |
+
cursor_position: int = 0
|
35 |
+
|
36 |
+
|
37 |
+
class BaseComplexPrompt(BaseSimplePrompt):
|
38 |
+
"""A base class to create a more complex prompt that will involve :class:`~prompt_toolkit.application.Application`.
|
39 |
+
|
40 |
+
Note:
|
41 |
+
This class does not create :class:`~prompt_toolkit.layout.Layout` nor :class:`~prompt_toolkit.application.Application`,
|
42 |
+
it only contains the necessary attributes and helper functions to be consumed.
|
43 |
+
|
44 |
+
Note:
|
45 |
+
Use :class:`~InquirerPy.base.BaseListPrompt` to create a complex list prompt which involves multiple choices. It has
|
46 |
+
more methods and helper function implemented.
|
47 |
+
|
48 |
+
See Also:
|
49 |
+
:class:`~InquirerPy.base.BaseListPrompt`
|
50 |
+
:class:`~InquirerPy.prompts.fuzzy.FuzzyPrompt`
|
51 |
+
"""
|
52 |
+
|
53 |
+
def __init__(
|
54 |
+
self,
|
55 |
+
message: Union[str, Callable[[InquirerPySessionResult], str]],
|
56 |
+
style: Optional[InquirerPyStyle] = None,
|
57 |
+
border: bool = False,
|
58 |
+
vi_mode: bool = False,
|
59 |
+
qmark: str = "?",
|
60 |
+
amark: str = "?",
|
61 |
+
instruction: str = "",
|
62 |
+
long_instruction: str = "",
|
63 |
+
transformer: Optional[Callable[[Any], Any]] = None,
|
64 |
+
filter: Optional[Callable[[Any], Any]] = None,
|
65 |
+
validate: Optional[InquirerPyValidate] = None,
|
66 |
+
invalid_message: str = "Invalid input",
|
67 |
+
wrap_lines: bool = True,
|
68 |
+
raise_keyboard_interrupt: bool = True,
|
69 |
+
mandatory: bool = True,
|
70 |
+
mandatory_message: str = "Mandatory prompt",
|
71 |
+
session_result: Optional[InquirerPySessionResult] = None,
|
72 |
+
) -> None:
|
73 |
+
super().__init__(
|
74 |
+
message=message,
|
75 |
+
style=style,
|
76 |
+
vi_mode=vi_mode,
|
77 |
+
qmark=qmark,
|
78 |
+
amark=amark,
|
79 |
+
instruction=instruction,
|
80 |
+
transformer=transformer,
|
81 |
+
filter=filter,
|
82 |
+
invalid_message=invalid_message,
|
83 |
+
validate=validate,
|
84 |
+
wrap_lines=wrap_lines,
|
85 |
+
raise_keyboard_interrupt=raise_keyboard_interrupt,
|
86 |
+
mandatory=mandatory,
|
87 |
+
mandatory_message=mandatory_message,
|
88 |
+
session_result=session_result,
|
89 |
+
)
|
90 |
+
self._invalid_message = invalid_message
|
91 |
+
self._rendered = False
|
92 |
+
self._invalid = False
|
93 |
+
self._loading = False
|
94 |
+
self._application: Application
|
95 |
+
self._long_instruction = long_instruction
|
96 |
+
self._border = border
|
97 |
+
self._height_offset = 2 # prev prompt result + current prompt question
|
98 |
+
if self._border:
|
99 |
+
self._height_offset += 2
|
100 |
+
if self._long_instruction:
|
101 |
+
self._height_offset += 1
|
102 |
+
self._validation_window_bottom_offset = 0 if not self._long_instruction else 1
|
103 |
+
if self._wrap_lines:
|
104 |
+
self._validation_window_bottom_offset += (
|
105 |
+
self.extra_long_instruction_line_count
|
106 |
+
)
|
107 |
+
|
108 |
+
self._is_vim_edit = Condition(lambda: self._editing_mode == EditingMode.VI)
|
109 |
+
self._is_invalid = Condition(lambda: self._invalid)
|
110 |
+
self._is_displaying_long_instruction = Condition(
|
111 |
+
lambda: self._long_instruction != ""
|
112 |
+
)
|
113 |
+
|
114 |
+
def _redraw(self) -> None:
|
115 |
+
"""Redraw the application UI."""
|
116 |
+
self._application.invalidate()
|
117 |
+
|
118 |
+
def register_kb(
|
119 |
+
self, *keys: Union[Keys, str], filter: FilterOrBool = True
|
120 |
+
) -> Callable[[KeyHandlerCallable], KeyHandlerCallable]:
|
121 |
+
"""Decorate keybinding registration function.
|
122 |
+
|
123 |
+
Ensure that the `invalid` state is cleared on next keybinding entered.
|
124 |
+
"""
|
125 |
+
kb_dec = super().register_kb(*keys, filter=filter)
|
126 |
+
|
127 |
+
def decorator(func: KeyHandlerCallable) -> KeyHandlerCallable:
|
128 |
+
@kb_dec
|
129 |
+
def executable(event):
|
130 |
+
if self._invalid:
|
131 |
+
self._invalid = False
|
132 |
+
func(event)
|
133 |
+
|
134 |
+
return executable
|
135 |
+
|
136 |
+
return decorator
|
137 |
+
|
138 |
+
def _exception_handler(self, _, context) -> None:
|
139 |
+
"""Set exception handler for the event loop.
|
140 |
+
|
141 |
+
Skip the question and raise exception.
|
142 |
+
|
143 |
+
Args:
|
144 |
+
loop: Current event loop.
|
145 |
+
context: Exception context.
|
146 |
+
"""
|
147 |
+
self._status["answered"] = True
|
148 |
+
self._status["result"] = INQUIRERPY_KEYBOARD_INTERRUPT
|
149 |
+
self._status["skipped"] = True
|
150 |
+
self._application.exit(exception=context["exception"])
|
151 |
+
|
152 |
+
def _after_render(self, app: Optional[Application]) -> None:
|
153 |
+
"""Run after the :class:`~prompt_toolkit.application.Application` is rendered/updated.
|
154 |
+
|
155 |
+
Since this function is fired up on each render, adding a check on `self._rendered` to
|
156 |
+
process logics that should only run once.
|
157 |
+
|
158 |
+
Set event loop exception handler here, since its guaranteed that the event loop is running
|
159 |
+
in `_after_render`.
|
160 |
+
"""
|
161 |
+
if not self._rendered:
|
162 |
+
self._rendered = True
|
163 |
+
|
164 |
+
self._keybinding_factory()
|
165 |
+
self._on_rendered(app)
|
166 |
+
|
167 |
+
def _set_error(self, message: str) -> None:
|
168 |
+
"""Set error message and set invalid state.
|
169 |
+
|
170 |
+
Args:
|
171 |
+
message: Error message to display.
|
172 |
+
"""
|
173 |
+
self._invalid_message = message
|
174 |
+
self._invalid = True
|
175 |
+
|
176 |
+
def _get_error_message(self) -> List[Tuple[str, str]]:
|
177 |
+
"""Obtain the error message dynamically.
|
178 |
+
|
179 |
+
Returns:
|
180 |
+
FormattedText in list of tuple format.
|
181 |
+
"""
|
182 |
+
return [
|
183 |
+
(
|
184 |
+
"class:validation-toolbar",
|
185 |
+
self._invalid_message,
|
186 |
+
)
|
187 |
+
]
|
188 |
+
|
189 |
+
def _on_rendered(self, _: Optional[Application]) -> None:
|
190 |
+
"""Run once after the UI is rendered. Acts like `ComponentDidMount`."""
|
191 |
+
pass
|
192 |
+
|
193 |
+
def _get_prompt_message(self) -> List[Tuple[str, str]]:
|
194 |
+
"""Get the prompt message to display.
|
195 |
+
|
196 |
+
Returns:
|
197 |
+
Formatted text in list of tuple format.
|
198 |
+
"""
|
199 |
+
pre_answer = (
|
200 |
+
"class:instruction",
|
201 |
+
" %s " % self.instruction if self.instruction else " ",
|
202 |
+
)
|
203 |
+
post_answer = ("class:answer", " %s" % self.status["result"])
|
204 |
+
return super()._get_prompt_message(pre_answer, post_answer)
|
205 |
+
|
206 |
+
def _run(self) -> Any:
|
207 |
+
"""Run the application."""
|
208 |
+
return self.application.run()
|
209 |
+
|
210 |
+
async def _run_async(self) -> None:
|
211 |
+
"""Run the application asynchronously."""
|
212 |
+
return await self.application.run_async()
|
213 |
+
|
214 |
+
@property
|
215 |
+
def application(self) -> Application:
|
216 |
+
"""Get the application.
|
217 |
+
|
218 |
+
:class:`.BaseComplexPrompt` requires :attr:`.BaseComplexPrompt._application` to be defined since this class
|
219 |
+
doesn't implement :class:`~prompt_toolkit.layout.Layout` and :class:`~prompt_toolkit.application.Application`.
|
220 |
+
|
221 |
+
Raises:
|
222 |
+
NotImplementedError: When `self._application` is not defined.
|
223 |
+
"""
|
224 |
+
if not self._application:
|
225 |
+
raise NotImplementedError
|
226 |
+
return self._application
|
227 |
+
|
228 |
+
@application.setter
|
229 |
+
def application(self, value: Application) -> None:
|
230 |
+
self._application = value
|
231 |
+
|
232 |
+
@property
|
233 |
+
def height_offset(self) -> int:
|
234 |
+
"""int: Height offset to apply."""
|
235 |
+
if not self._wrap_lines:
|
236 |
+
return self._height_offset
|
237 |
+
return self.extra_line_count + self._height_offset
|
238 |
+
|
239 |
+
@property
|
240 |
+
def total_message_length(self) -> int:
|
241 |
+
"""int: Total length of the message."""
|
242 |
+
total_message_length = 0
|
243 |
+
if self._qmark:
|
244 |
+
total_message_length += len(self._qmark)
|
245 |
+
total_message_length += 1 # Extra space if qmark is present
|
246 |
+
total_message_length += len(str(self._message))
|
247 |
+
total_message_length += 1 # Extra space between message and instruction
|
248 |
+
total_message_length += len(str(self._instruction))
|
249 |
+
if self._instruction:
|
250 |
+
total_message_length += 1 # Extra space behind the instruction
|
251 |
+
return total_message_length
|
252 |
+
|
253 |
+
@property
|
254 |
+
def extra_message_line_count(self) -> int:
|
255 |
+
"""int: Get the extra lines created caused by line wrapping.
|
256 |
+
|
257 |
+
Minus 1 on the totoal message length as we only want the extra line.
|
258 |
+
24 // 24 will equal to 1 however we only want the value to be 1 when we have 25 char
|
259 |
+
which will create an extra line.
|
260 |
+
"""
|
261 |
+
term_width, _ = shutil.get_terminal_size()
|
262 |
+
return (self.total_message_length - 1) // term_width
|
263 |
+
|
264 |
+
@property
|
265 |
+
def extra_long_instruction_line_count(self) -> int:
|
266 |
+
"""int: Get the extra lines created caused by line wrapping.
|
267 |
+
|
268 |
+
See Also:
|
269 |
+
:attr:`.BaseComplexPrompt.extra_message_line_count`
|
270 |
+
"""
|
271 |
+
if self._long_instruction:
|
272 |
+
term_width, _ = shutil.get_terminal_size()
|
273 |
+
return (len(self._long_instruction) - 1) // term_width
|
274 |
+
else:
|
275 |
+
return 0
|
276 |
+
|
277 |
+
@property
|
278 |
+
def extra_line_count(self) -> int:
|
279 |
+
"""Get the extra lines created caused by line wrapping.
|
280 |
+
|
281 |
+
Used mainly to calculate how much additional offset should be applied when getting
|
282 |
+
the height.
|
283 |
+
|
284 |
+
Returns:
|
285 |
+
Total extra lines created due to line wrapping.
|
286 |
+
"""
|
287 |
+
result = 0
|
288 |
+
|
289 |
+
# message wrap
|
290 |
+
result += self.extra_message_line_count
|
291 |
+
# long instruction wrap
|
292 |
+
result += self.extra_long_instruction_line_count
|
293 |
+
|
294 |
+
return result
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/control.py
ADDED
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Contains the content control class :class:`.InquirerPyUIListControl`."""
|
2 |
+
from abc import abstractmethod
|
3 |
+
from dataclasses import asdict, dataclass
|
4 |
+
from typing import Any, Callable, Dict, List, Optional, Tuple, cast
|
5 |
+
|
6 |
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
7 |
+
|
8 |
+
from InquirerPy.exceptions import InvalidArgument, RequiredKeyNotFound
|
9 |
+
from InquirerPy.separator import Separator
|
10 |
+
from InquirerPy.utils import InquirerPyListChoices, InquirerPySessionResult
|
11 |
+
|
12 |
+
__all__ = ["Choice", "InquirerPyUIListControl"]
|
13 |
+
|
14 |
+
|
15 |
+
@dataclass
|
16 |
+
class Choice:
|
17 |
+
"""Class to create choices for list type prompts.
|
18 |
+
|
19 |
+
A simple dataclass that can be used as an alternate to using :class:`dict`
|
20 |
+
when working with choices.
|
21 |
+
|
22 |
+
Args:
|
23 |
+
value: The value of the choice when user selects this choice.
|
24 |
+
name: The value that should be presented to the user prior/after selection of the choice.
|
25 |
+
This value is optional, if not provided, it will fallback to the string representation of `value`.
|
26 |
+
enabled: Indicates if the choice should be pre-selected.
|
27 |
+
This only has effects when the prompt has `multiselect` enabled.
|
28 |
+
"""
|
29 |
+
|
30 |
+
value: Any
|
31 |
+
name: Optional[str] = None
|
32 |
+
enabled: bool = False
|
33 |
+
|
34 |
+
def __post_init__(self):
|
35 |
+
"""Assign strinify value to name if not present."""
|
36 |
+
if self.name is None:
|
37 |
+
self.name = str(self.value)
|
38 |
+
|
39 |
+
|
40 |
+
class InquirerPyUIListControl(FormattedTextControl):
|
41 |
+
"""A base class to create :class:`~prompt_toolkit.layout.UIControl` to display list type contents.
|
42 |
+
|
43 |
+
Args:
|
44 |
+
choices(InquirerPyListChoices): List of choices to display as the content.
|
45 |
+
Can also be a callable or async callable that returns a list of choices.
|
46 |
+
default: Default value, this will affect the cursor position.
|
47 |
+
multiselect: Indicate if the current prompt has `multiselect` enabled.
|
48 |
+
session_result: Current session result.
|
49 |
+
"""
|
50 |
+
|
51 |
+
def __init__(
|
52 |
+
self,
|
53 |
+
choices: InquirerPyListChoices,
|
54 |
+
default: Any = None,
|
55 |
+
multiselect: bool = False,
|
56 |
+
session_result: Optional[InquirerPySessionResult] = None,
|
57 |
+
) -> None:
|
58 |
+
self._session_result = session_result or {}
|
59 |
+
self._selected_choice_index: int = 0
|
60 |
+
self._choice_func = None
|
61 |
+
self._multiselect = multiselect
|
62 |
+
self._default = (
|
63 |
+
default
|
64 |
+
if not isinstance(default, Callable)
|
65 |
+
else cast(Callable, default)(self._session_result)
|
66 |
+
)
|
67 |
+
self._raw_choices = (
|
68 |
+
choices
|
69 |
+
if not isinstance(choices, Callable)
|
70 |
+
else cast(Callable, choices)(self._session_result)
|
71 |
+
)
|
72 |
+
self._choices = self._get_choices(self._raw_choices, self._default)
|
73 |
+
self._safety_check()
|
74 |
+
self._format_choices()
|
75 |
+
super().__init__(self._get_formatted_choices)
|
76 |
+
|
77 |
+
def _get_choices(self, choices: List[Any], default: Any) -> List[Dict[str, Any]]:
|
78 |
+
"""Process the raw user input choices and format it into dictionary.
|
79 |
+
|
80 |
+
Args:
|
81 |
+
choices: List of chices to display.
|
82 |
+
default: Default value, this will affect the :attr:`.InquirerPyUIListControl.selected_choice_index`
|
83 |
+
|
84 |
+
Returns:
|
85 |
+
List of choices.
|
86 |
+
|
87 |
+
Raises:
|
88 |
+
RequiredKeyNotFound: When the provided choice is missing the `name` or `value` key.
|
89 |
+
"""
|
90 |
+
processed_choices: List[Dict[str, Any]] = []
|
91 |
+
try:
|
92 |
+
for index, choice in enumerate(choices, start=0):
|
93 |
+
if isinstance(choice, dict):
|
94 |
+
if choice["value"] == default:
|
95 |
+
self.selected_choice_index = index
|
96 |
+
processed_choices.append(
|
97 |
+
{
|
98 |
+
"name": str(choice["name"]),
|
99 |
+
"value": choice["value"],
|
100 |
+
"enabled": choice.get("enabled", False)
|
101 |
+
if self._multiselect
|
102 |
+
else False,
|
103 |
+
}
|
104 |
+
)
|
105 |
+
elif isinstance(choice, Separator):
|
106 |
+
if self.selected_choice_index == index:
|
107 |
+
self.selected_choice_index = (
|
108 |
+
self.selected_choice_index + 1
|
109 |
+
) % len(choices)
|
110 |
+
processed_choices.append(
|
111 |
+
{"name": str(choice), "value": choice, "enabled": False}
|
112 |
+
)
|
113 |
+
elif isinstance(choice, Choice):
|
114 |
+
dict_choice = asdict(choice)
|
115 |
+
if dict_choice["value"] == default:
|
116 |
+
self.selected_choice_index = index
|
117 |
+
if not self._multiselect:
|
118 |
+
dict_choice["enabled"] = False
|
119 |
+
processed_choices.append(dict_choice)
|
120 |
+
else:
|
121 |
+
if choice == default:
|
122 |
+
self.selected_choice_index = index
|
123 |
+
processed_choices.append(
|
124 |
+
{"name": str(choice), "value": choice, "enabled": False}
|
125 |
+
)
|
126 |
+
except KeyError:
|
127 |
+
raise RequiredKeyNotFound(
|
128 |
+
"dictionary type of choice require a 'name' key and a 'value' key"
|
129 |
+
)
|
130 |
+
return processed_choices
|
131 |
+
|
132 |
+
@property
|
133 |
+
def selected_choice_index(self) -> int:
|
134 |
+
"""int: Current highlighted index."""
|
135 |
+
return self._selected_choice_index
|
136 |
+
|
137 |
+
@selected_choice_index.setter
|
138 |
+
def selected_choice_index(self, value: int) -> None:
|
139 |
+
self._selected_choice_index = value
|
140 |
+
|
141 |
+
@property
|
142 |
+
def choices(self) -> List[Dict[str, Any]]:
|
143 |
+
"""List[Dict[str, Any]]: Get all processed choices."""
|
144 |
+
return self._choices
|
145 |
+
|
146 |
+
@choices.setter
|
147 |
+
def choices(self, value: List[Dict[str, Any]]) -> None:
|
148 |
+
self._choices = value
|
149 |
+
|
150 |
+
def _safety_check(self) -> None:
|
151 |
+
"""Validate processed choices.
|
152 |
+
|
153 |
+
Check if the choices are empty or if it only contains :class:`~InquirerPy.separator.Separator`.
|
154 |
+
"""
|
155 |
+
if not self.choices:
|
156 |
+
raise InvalidArgument("argument choices cannot be empty")
|
157 |
+
should_proceed: bool = False
|
158 |
+
for choice in self.choices:
|
159 |
+
if not isinstance(choice["value"], Separator):
|
160 |
+
should_proceed = True
|
161 |
+
break
|
162 |
+
if not should_proceed:
|
163 |
+
raise InvalidArgument(
|
164 |
+
"argument choices should contain choices other than separator"
|
165 |
+
)
|
166 |
+
|
167 |
+
def _get_formatted_choices(self) -> List[Tuple[str, str]]:
|
168 |
+
"""Get all choices in formatted text format.
|
169 |
+
|
170 |
+
Returns:
|
171 |
+
List of choices in formatted text form.
|
172 |
+
"""
|
173 |
+
display_choices = []
|
174 |
+
|
175 |
+
for index, choice in enumerate(self.choices):
|
176 |
+
if index == self.selected_choice_index:
|
177 |
+
display_choices += self._get_hover_text(choice)
|
178 |
+
else:
|
179 |
+
display_choices += self._get_normal_text(choice)
|
180 |
+
display_choices.append(("", "\n"))
|
181 |
+
if display_choices:
|
182 |
+
display_choices.pop()
|
183 |
+
return display_choices
|
184 |
+
|
185 |
+
def _format_choices(self) -> None:
|
186 |
+
"""Perform post processing on the choices.
|
187 |
+
|
188 |
+
Additional customisation to the choices after :meth:`.InquirerPyUIListControl._get_choices` call.
|
189 |
+
"""
|
190 |
+
pass
|
191 |
+
|
192 |
+
@abstractmethod
|
193 |
+
def _get_hover_text(self, choice) -> List[Tuple[str, str]]:
|
194 |
+
"""Generate the formatted text for hovered choice.
|
195 |
+
|
196 |
+
Returns:
|
197 |
+
Formatted text in list of tuple format.
|
198 |
+
"""
|
199 |
+
pass
|
200 |
+
|
201 |
+
@abstractmethod
|
202 |
+
def _get_normal_text(self, choice) -> List[Tuple[str, str]]:
|
203 |
+
"""Generate the formatted text for non-hovered choices.
|
204 |
+
|
205 |
+
Returns:
|
206 |
+
Formatted text in list of tuple format.
|
207 |
+
"""
|
208 |
+
pass
|
209 |
+
|
210 |
+
@property
|
211 |
+
def choice_count(self) -> int:
|
212 |
+
"""int: Total count of choices."""
|
213 |
+
return len(self.choices)
|
214 |
+
|
215 |
+
@property
|
216 |
+
def selection(self) -> Dict[str, Any]:
|
217 |
+
"""Dict[str, Any]: Current selected choice."""
|
218 |
+
return self.choices[self.selected_choice_index]
|
219 |
+
|
220 |
+
@property
|
221 |
+
def loading(self) -> bool:
|
222 |
+
"""bool: Indicate if the content control is loading."""
|
223 |
+
return self._loading
|
224 |
+
|
225 |
+
@loading.setter
|
226 |
+
def loading(self, value: bool) -> None:
|
227 |
+
self._loading = value
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/list.py
ADDED
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Contains the base class :class:`.BaseListPrompt` which can be used to create a prompt involving choices."""
|
2 |
+
from abc import abstractmethod
|
3 |
+
from typing import Any, Callable, List, Optional
|
4 |
+
|
5 |
+
from prompt_toolkit.filters.base import Condition
|
6 |
+
from prompt_toolkit.keys import Keys
|
7 |
+
|
8 |
+
from InquirerPy.base.complex import BaseComplexPrompt
|
9 |
+
from InquirerPy.base.control import InquirerPyUIListControl
|
10 |
+
from InquirerPy.separator import Separator
|
11 |
+
from InquirerPy.utils import (
|
12 |
+
InquirerPyKeybindings,
|
13 |
+
InquirerPyMessage,
|
14 |
+
InquirerPySessionResult,
|
15 |
+
InquirerPyStyle,
|
16 |
+
InquirerPyValidate,
|
17 |
+
)
|
18 |
+
|
19 |
+
|
20 |
+
class BaseListPrompt(BaseComplexPrompt):
|
21 |
+
"""A base class to create a complex prompt involving choice selections (i.e. list) using `prompt_toolkit` Application.
|
22 |
+
|
23 |
+
Note:
|
24 |
+
This class does not create :class:`~prompt_toolkit.layout.Layout` nor :class:`~prompt_toolkit.application.Application`,
|
25 |
+
it only contains the necessary attributes and helper functions to be consumed.
|
26 |
+
|
27 |
+
See Also:
|
28 |
+
:class:`~InquirerPy.prompts.list.ListPrompt`
|
29 |
+
:class:`~InquirerPy.prompts.fuzzy.FuzzyPrompt`
|
30 |
+
"""
|
31 |
+
|
32 |
+
def __init__(
|
33 |
+
self,
|
34 |
+
message: InquirerPyMessage,
|
35 |
+
style: Optional[InquirerPyStyle] = None,
|
36 |
+
vi_mode: bool = False,
|
37 |
+
qmark: str = "?",
|
38 |
+
amark: str = "?",
|
39 |
+
instruction: str = "",
|
40 |
+
long_instruction: str = "",
|
41 |
+
border: bool = False,
|
42 |
+
transformer: Optional[Callable[[Any], Any]] = None,
|
43 |
+
filter: Optional[Callable[[Any], Any]] = None,
|
44 |
+
validate: Optional[InquirerPyValidate] = None,
|
45 |
+
invalid_message: str = "Invalid input",
|
46 |
+
multiselect: bool = False,
|
47 |
+
keybindings: Optional[InquirerPyKeybindings] = None,
|
48 |
+
cycle: bool = True,
|
49 |
+
wrap_lines: bool = True,
|
50 |
+
raise_keyboard_interrupt: bool = True,
|
51 |
+
mandatory: bool = True,
|
52 |
+
mandatory_message: str = "Mandatory prompt",
|
53 |
+
session_result: Optional[InquirerPySessionResult] = None,
|
54 |
+
) -> None:
|
55 |
+
super().__init__(
|
56 |
+
message=message,
|
57 |
+
style=style,
|
58 |
+
border=border,
|
59 |
+
vi_mode=vi_mode,
|
60 |
+
qmark=qmark,
|
61 |
+
amark=amark,
|
62 |
+
transformer=transformer,
|
63 |
+
filter=filter,
|
64 |
+
invalid_message=invalid_message,
|
65 |
+
validate=validate,
|
66 |
+
instruction=instruction,
|
67 |
+
long_instruction=long_instruction,
|
68 |
+
wrap_lines=wrap_lines,
|
69 |
+
raise_keyboard_interrupt=raise_keyboard_interrupt,
|
70 |
+
mandatory=mandatory,
|
71 |
+
mandatory_message=mandatory_message,
|
72 |
+
session_result=session_result,
|
73 |
+
)
|
74 |
+
|
75 |
+
self._content_control: InquirerPyUIListControl
|
76 |
+
self._multiselect = multiselect
|
77 |
+
self._is_multiselect = Condition(lambda: self._multiselect)
|
78 |
+
self._cycle = cycle
|
79 |
+
|
80 |
+
if not keybindings:
|
81 |
+
keybindings = {}
|
82 |
+
|
83 |
+
self.kb_maps = {
|
84 |
+
"down": [
|
85 |
+
{"key": "down"},
|
86 |
+
{"key": "c-n", "filter": ~self._is_vim_edit},
|
87 |
+
{"key": "j", "filter": self._is_vim_edit},
|
88 |
+
],
|
89 |
+
"up": [
|
90 |
+
{"key": "up"},
|
91 |
+
{"key": "c-p", "filter": ~self._is_vim_edit},
|
92 |
+
{"key": "k", "filter": self._is_vim_edit},
|
93 |
+
],
|
94 |
+
"toggle": [
|
95 |
+
{"key": "space"},
|
96 |
+
],
|
97 |
+
"toggle-down": [
|
98 |
+
{"key": Keys.Tab},
|
99 |
+
],
|
100 |
+
"toggle-up": [
|
101 |
+
{"key": Keys.BackTab},
|
102 |
+
],
|
103 |
+
"toggle-all": [
|
104 |
+
{"key": "alt-r"},
|
105 |
+
{"key": "c-r"},
|
106 |
+
],
|
107 |
+
"toggle-all-true": [
|
108 |
+
{"key": "alt-a"},
|
109 |
+
{"key": "c-a"},
|
110 |
+
],
|
111 |
+
"toggle-all-false": [],
|
112 |
+
**keybindings,
|
113 |
+
}
|
114 |
+
|
115 |
+
self.kb_func_lookup = {
|
116 |
+
"down": [{"func": self._handle_down}],
|
117 |
+
"up": [{"func": self._handle_up}],
|
118 |
+
"toggle": [{"func": self._handle_toggle_choice}],
|
119 |
+
"toggle-down": [
|
120 |
+
{"func": self._handle_toggle_choice},
|
121 |
+
{"func": self._handle_down},
|
122 |
+
],
|
123 |
+
"toggle-up": [
|
124 |
+
{"func": self._handle_toggle_choice},
|
125 |
+
{"func": self._handle_up},
|
126 |
+
],
|
127 |
+
"toggle-all": [{"func": self._handle_toggle_all}],
|
128 |
+
"toggle-all-true": [{"func": self._handle_toggle_all, "args": [True]}],
|
129 |
+
"toggle-all-false": [{"func": self._handle_toggle_all, "args": [False]}],
|
130 |
+
}
|
131 |
+
|
132 |
+
@property
|
133 |
+
def content_control(self) -> InquirerPyUIListControl:
|
134 |
+
"""Get the content controller object.
|
135 |
+
|
136 |
+
Needs to be an instance of :class:`~InquirerPy.base.control.InquirerPyUIListControl`.
|
137 |
+
|
138 |
+
Each :class:`.BaseComplexPrompt` requires a `content_control` to display custom
|
139 |
+
contents for the prompt.
|
140 |
+
|
141 |
+
Raises:
|
142 |
+
NotImplementedError: When `self._content_control` is not found.
|
143 |
+
"""
|
144 |
+
if not self._content_control:
|
145 |
+
raise NotImplementedError
|
146 |
+
return self._content_control
|
147 |
+
|
148 |
+
@content_control.setter
|
149 |
+
def content_control(self, value: InquirerPyUIListControl) -> None:
|
150 |
+
self._content_control = value
|
151 |
+
|
152 |
+
@property
|
153 |
+
def result_name(self) -> Any:
|
154 |
+
"""Get the result value that should be printed to the terminal.
|
155 |
+
|
156 |
+
In multiselect scenario, return result as a list.
|
157 |
+
"""
|
158 |
+
if self._multiselect:
|
159 |
+
return [choice["name"] for choice in self.selected_choices]
|
160 |
+
else:
|
161 |
+
try:
|
162 |
+
return self.content_control.selection["name"]
|
163 |
+
except IndexError:
|
164 |
+
return ""
|
165 |
+
|
166 |
+
@property
|
167 |
+
def result_value(self) -> Any:
|
168 |
+
"""Get the result value that should return to the user.
|
169 |
+
|
170 |
+
In multiselect scenario, return result as a list.
|
171 |
+
"""
|
172 |
+
if self._multiselect:
|
173 |
+
return [choice["value"] for choice in self.selected_choices]
|
174 |
+
else:
|
175 |
+
try:
|
176 |
+
return self.content_control.selection["value"]
|
177 |
+
except IndexError:
|
178 |
+
return ""
|
179 |
+
|
180 |
+
@property
|
181 |
+
def selected_choices(self) -> List[Any]:
|
182 |
+
"""List[Any]: Get all user selected choices."""
|
183 |
+
|
184 |
+
def filter_choice(choice):
|
185 |
+
return not isinstance(choice, Separator) and choice["enabled"]
|
186 |
+
|
187 |
+
return list(filter(filter_choice, self.content_control.choices))
|
188 |
+
|
189 |
+
def _handle_down(self, _) -> bool:
|
190 |
+
"""Handle event when user attempts to move down.
|
191 |
+
|
192 |
+
Returns:
|
193 |
+
Boolean indicating if the action hits the cap.
|
194 |
+
"""
|
195 |
+
if self._cycle:
|
196 |
+
self.content_control.selected_choice_index = (
|
197 |
+
self.content_control.selected_choice_index + 1
|
198 |
+
) % self.content_control.choice_count
|
199 |
+
return False
|
200 |
+
else:
|
201 |
+
self.content_control.selected_choice_index += 1
|
202 |
+
if (
|
203 |
+
self.content_control.selected_choice_index
|
204 |
+
>= self.content_control.choice_count
|
205 |
+
):
|
206 |
+
self.content_control.selected_choice_index = (
|
207 |
+
self.content_control.choice_count - 1
|
208 |
+
)
|
209 |
+
return True
|
210 |
+
return False
|
211 |
+
|
212 |
+
def _handle_up(self, _) -> bool:
|
213 |
+
"""Handle event when user attempts to move up.
|
214 |
+
|
215 |
+
Returns:
|
216 |
+
Boolean indicating if the action hits the cap.
|
217 |
+
"""
|
218 |
+
if self._cycle:
|
219 |
+
self.content_control.selected_choice_index = (
|
220 |
+
self.content_control.selected_choice_index - 1
|
221 |
+
) % self.content_control.choice_count
|
222 |
+
return False
|
223 |
+
else:
|
224 |
+
self.content_control.selected_choice_index -= 1
|
225 |
+
if self.content_control.selected_choice_index < 0:
|
226 |
+
self.content_control.selected_choice_index = 0
|
227 |
+
return True
|
228 |
+
return False
|
229 |
+
|
230 |
+
@abstractmethod
|
231 |
+
def _handle_toggle_choice(self, event) -> None:
|
232 |
+
"""Handle event when user attempting to toggle the state of the chocie."""
|
233 |
+
pass
|
234 |
+
|
235 |
+
@abstractmethod
|
236 |
+
def _handle_toggle_all(self, event, value: bool) -> None:
|
237 |
+
"""Handle event when user attempting to alter the state of all choices."""
|
238 |
+
pass
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/base/simple.py
ADDED
@@ -0,0 +1,378 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Contains the base class :class:`.BaseSimplePrompt`."""
|
2 |
+
import os
|
3 |
+
import re
|
4 |
+
from abc import ABC, abstractmethod
|
5 |
+
from typing import (
|
6 |
+
TYPE_CHECKING,
|
7 |
+
Any,
|
8 |
+
Callable,
|
9 |
+
Dict,
|
10 |
+
List,
|
11 |
+
Optional,
|
12 |
+
Tuple,
|
13 |
+
Union,
|
14 |
+
cast,
|
15 |
+
)
|
16 |
+
|
17 |
+
from prompt_toolkit.enums import EditingMode
|
18 |
+
from prompt_toolkit.filters.base import Condition, FilterOrBool
|
19 |
+
from prompt_toolkit.key_binding.key_bindings import KeyBindings, KeyHandlerCallable
|
20 |
+
from prompt_toolkit.keys import Keys
|
21 |
+
from prompt_toolkit.styles.style import Style
|
22 |
+
from prompt_toolkit.validation import Validator
|
23 |
+
|
24 |
+
from InquirerPy.enum import INQUIRERPY_KEYBOARD_INTERRUPT
|
25 |
+
from InquirerPy.exceptions import RequiredKeyNotFound
|
26 |
+
from InquirerPy.utils import (
|
27 |
+
InquirerPyMessage,
|
28 |
+
InquirerPySessionResult,
|
29 |
+
InquirerPyStyle,
|
30 |
+
InquirerPyValidate,
|
31 |
+
get_style,
|
32 |
+
)
|
33 |
+
|
34 |
+
if TYPE_CHECKING:
|
35 |
+
from prompt_toolkit.key_binding.key_processor import KeyPressEvent
|
36 |
+
|
37 |
+
|
38 |
+
class BaseSimplePrompt(ABC):
|
39 |
+
"""The base class to create a simple terminal input prompt.
|
40 |
+
|
41 |
+
Note:
|
42 |
+
No actual :class:`~prompt_toolkit.application.Application` is created by this class.
|
43 |
+
This class only creates some common interface and attributes that can be easily used
|
44 |
+
by `prompt_toolkit`.
|
45 |
+
|
46 |
+
To have a functional prompt, you'll at least have to implement the :meth:`.BaseSimplePrompt._run`
|
47 |
+
and :meth:`.BaseSimplePrompt._get_prompt_message`.
|
48 |
+
|
49 |
+
See Also:
|
50 |
+
:class:`~InquirerPy.prompts.input.InputPrompt`
|
51 |
+
"""
|
52 |
+
|
53 |
+
def __init__(
|
54 |
+
self,
|
55 |
+
message: InquirerPyMessage,
|
56 |
+
style: Optional[InquirerPyStyle] = None,
|
57 |
+
vi_mode: bool = False,
|
58 |
+
qmark: str = "?",
|
59 |
+
amark: str = "?",
|
60 |
+
instruction: str = "",
|
61 |
+
validate: Optional[InquirerPyValidate] = None,
|
62 |
+
invalid_message: str = "Invalid input",
|
63 |
+
transformer: Optional[Callable[[Any], Any]] = None,
|
64 |
+
filter: Optional[Callable[[Any], Any]] = None,
|
65 |
+
default: Any = "",
|
66 |
+
wrap_lines: bool = True,
|
67 |
+
raise_keyboard_interrupt: bool = True,
|
68 |
+
mandatory: bool = True,
|
69 |
+
mandatory_message: str = "Mandatory prompt",
|
70 |
+
session_result: Optional[InquirerPySessionResult] = None,
|
71 |
+
) -> None:
|
72 |
+
self._mandatory = mandatory
|
73 |
+
self._mandatory_message = mandatory_message
|
74 |
+
self._result = session_result or {}
|
75 |
+
self._message = (
|
76 |
+
message
|
77 |
+
if not isinstance(message, Callable)
|
78 |
+
else cast(Callable, message)(self._result)
|
79 |
+
)
|
80 |
+
self._instruction = instruction
|
81 |
+
self._default = (
|
82 |
+
default if not isinstance(default, Callable) else default(self._result)
|
83 |
+
)
|
84 |
+
self._style = Style.from_dict(style.dict if style else get_style().dict)
|
85 |
+
self._qmark = qmark
|
86 |
+
self._amark = amark
|
87 |
+
self._status = {"answered": False, "result": None, "skipped": False}
|
88 |
+
self._kb = KeyBindings()
|
89 |
+
self._lexer = "class:input"
|
90 |
+
self._transformer = transformer
|
91 |
+
self._filter = filter
|
92 |
+
self._wrap_lines = wrap_lines
|
93 |
+
self._editing_mode = (
|
94 |
+
EditingMode.VI
|
95 |
+
if vi_mode or bool(os.getenv("INQUIRERPY_VI_MODE", False))
|
96 |
+
else EditingMode.EMACS
|
97 |
+
)
|
98 |
+
if isinstance(validate, Validator):
|
99 |
+
self._validator = validate
|
100 |
+
else:
|
101 |
+
self._validator = Validator.from_callable(
|
102 |
+
validate if validate else lambda _: True,
|
103 |
+
invalid_message,
|
104 |
+
move_cursor_to_end=True,
|
105 |
+
)
|
106 |
+
self._raise_kbi = not os.getenv(
|
107 |
+
"INQUIRERPY_NO_RAISE_KBI", not raise_keyboard_interrupt
|
108 |
+
)
|
109 |
+
self._is_rasing_kbi = Condition(lambda: self._raise_kbi)
|
110 |
+
|
111 |
+
self._kb_maps = {
|
112 |
+
"answer": [{"key": Keys.Enter}],
|
113 |
+
"interrupt": [
|
114 |
+
{"key": "c-c", "filter": self._is_rasing_kbi},
|
115 |
+
{"key": "c-d", "filter": ~self._is_rasing_kbi},
|
116 |
+
],
|
117 |
+
"skip": [{"key": "c-z"}, {"key": "c-c", "filter": ~self._is_rasing_kbi}],
|
118 |
+
}
|
119 |
+
self._kb_func_lookup = {
|
120 |
+
"answer": [{"func": self._handle_enter}],
|
121 |
+
"interrupt": [{"func": self._handle_interrupt}],
|
122 |
+
"skip": [{"func": self._handle_skip}],
|
123 |
+
}
|
124 |
+
|
125 |
+
def _keybinding_factory(self):
|
126 |
+
"""Register all keybindings in `self._kb_maps`.
|
127 |
+
|
128 |
+
It's required to call this function at the end of prompt constructor if
|
129 |
+
it inherits from :class:`~InquirerPy.base.simple.BaseSimplePrompt` or
|
130 |
+
:class:`~InquirerPy.base.complex.BaseComplexPrompt`.
|
131 |
+
"""
|
132 |
+
|
133 |
+
def _factory(keys, filter, action):
|
134 |
+
if action not in self.kb_func_lookup:
|
135 |
+
raise RequiredKeyNotFound(f"keybinding action {action} not found")
|
136 |
+
if not isinstance(keys, list):
|
137 |
+
keys = [keys]
|
138 |
+
|
139 |
+
@self.register_kb(*keys, filter=filter)
|
140 |
+
def _(event):
|
141 |
+
for method in self.kb_func_lookup[action]:
|
142 |
+
method["func"](event, *method.get("args", []))
|
143 |
+
|
144 |
+
for key, item in self.kb_maps.items():
|
145 |
+
if not isinstance(item, list):
|
146 |
+
item = [item]
|
147 |
+
for kb in item:
|
148 |
+
_factory(kb["key"], kb.get("filter", Condition(lambda: True)), key)
|
149 |
+
|
150 |
+
@abstractmethod
|
151 |
+
def _set_error(self, message: str) -> None:
|
152 |
+
"""Set the error message for the prompt.
|
153 |
+
|
154 |
+
Args:
|
155 |
+
message: Error message to set.
|
156 |
+
"""
|
157 |
+
pass
|
158 |
+
|
159 |
+
def _handle_skip(self, event: Optional["KeyPressEvent"]) -> None:
|
160 |
+
"""Handle the event when attempting to skip a prompt.
|
161 |
+
|
162 |
+
Skip the prompt if the `_mandatory` field is False, otherwise
|
163 |
+
show an error message that the prompt cannot be skipped.
|
164 |
+
"""
|
165 |
+
if not self._mandatory:
|
166 |
+
self.status["answered"] = True
|
167 |
+
self.status["skipped"] = True
|
168 |
+
self.status["result"] = None
|
169 |
+
if event:
|
170 |
+
event.app.exit(result=None)
|
171 |
+
else:
|
172 |
+
self._set_error(message=self._mandatory_message)
|
173 |
+
|
174 |
+
def _handle_interrupt(self, event: Optional["KeyPressEvent"]) -> None:
|
175 |
+
"""Handle the event when a KeyboardInterrupt signal is sent."""
|
176 |
+
self.status["answered"] = True
|
177 |
+
self.status["result"] = INQUIRERPY_KEYBOARD_INTERRUPT
|
178 |
+
self.status["skipped"] = True
|
179 |
+
if event:
|
180 |
+
event.app.exit(result=INQUIRERPY_KEYBOARD_INTERRUPT)
|
181 |
+
|
182 |
+
@abstractmethod
|
183 |
+
def _handle_enter(self, event: Optional["KeyPressEvent"]) -> None:
|
184 |
+
"""Handle the event when user attempt to answer the question."""
|
185 |
+
pass
|
186 |
+
|
187 |
+
@property
|
188 |
+
def status(self) -> Dict[str, Any]:
|
189 |
+
"""Dict[str, Any]: Get current prompt status.
|
190 |
+
|
191 |
+
The status contains 3 keys: "answered" and "result".
|
192 |
+
answered: If the current prompt is answered.
|
193 |
+
result: The result of the user answer.
|
194 |
+
skipped: If the prompt is skipped.
|
195 |
+
"""
|
196 |
+
return self._status
|
197 |
+
|
198 |
+
@status.setter
|
199 |
+
def status(self, value) -> None:
|
200 |
+
self._status = value
|
201 |
+
|
202 |
+
def register_kb(
|
203 |
+
self, *keys: Union[Keys, str], filter: FilterOrBool = True, **kwargs
|
204 |
+
) -> Callable[[KeyHandlerCallable], KeyHandlerCallable]:
|
205 |
+
"""Keybinding registration decorator.
|
206 |
+
|
207 |
+
This decorator wraps around the :meth:`prompt_toolkit.key_binding.KeyBindings.add` with
|
208 |
+
added feature to process `alt` realted keybindings.
|
209 |
+
|
210 |
+
By default, `prompt_toolkit` doesn't process `alt` related keybindings,
|
211 |
+
it requires `alt-ANY` to `escape` + `ANY`.
|
212 |
+
|
213 |
+
Args:
|
214 |
+
keys: The keys to bind that can trigger the function.
|
215 |
+
filter: :class:`~prompt_toolkit.filter.Condition` to indicate if this keybinding should be active.
|
216 |
+
|
217 |
+
Returns:
|
218 |
+
A decorator that should be applied to the function thats intended to be active when the keys
|
219 |
+
are pressed.
|
220 |
+
|
221 |
+
Examples:
|
222 |
+
>>> @self.register_kb("alt-j")
|
223 |
+
... def test(event):
|
224 |
+
... pass
|
225 |
+
"""
|
226 |
+
alt_pattern = re.compile(r"^alt-(.*)")
|
227 |
+
|
228 |
+
def decorator(func: KeyHandlerCallable) -> KeyHandlerCallable:
|
229 |
+
formatted_keys = []
|
230 |
+
for key in keys:
|
231 |
+
match = alt_pattern.match(key)
|
232 |
+
if match:
|
233 |
+
formatted_keys.append("escape")
|
234 |
+
formatted_keys.append(match.group(1))
|
235 |
+
else:
|
236 |
+
formatted_keys.append(key)
|
237 |
+
|
238 |
+
@self._kb.add(*formatted_keys, filter=filter, **kwargs)
|
239 |
+
def executable(event) -> None:
|
240 |
+
func(event)
|
241 |
+
|
242 |
+
return executable
|
243 |
+
|
244 |
+
return decorator
|
245 |
+
|
246 |
+
@abstractmethod
|
247 |
+
def _get_prompt_message(
|
248 |
+
self, pre_answer: Tuple[str, str], post_answer: Tuple[str, str]
|
249 |
+
) -> List[Tuple[str, str]]:
|
250 |
+
"""Get the question message in formatted text form to display in the prompt.
|
251 |
+
|
252 |
+
This function is mainly used to render the question message dynamically based
|
253 |
+
on the current status (answered or not answered) of the prompt.
|
254 |
+
|
255 |
+
Note:
|
256 |
+
The function requires implementation when inheriting :class:`.BaseSimplePrompt`.
|
257 |
+
You should call `super()._get_prompt_message(pre_answer, post_answer)` in
|
258 |
+
the implemented `_get_prompt_message`.
|
259 |
+
|
260 |
+
Args:
|
261 |
+
pre_answer: The message to display before the question is answered.
|
262 |
+
post_answer: The information to display after the question is answered.
|
263 |
+
|
264 |
+
Returns:
|
265 |
+
Formatted text in list of tuple format.
|
266 |
+
"""
|
267 |
+
display_message = []
|
268 |
+
if self.status["skipped"]:
|
269 |
+
display_message.append(("class:skipped", self._qmark))
|
270 |
+
display_message.append(
|
271 |
+
("class:skipped", "%s%s " % (" " if self._qmark else "", self._message))
|
272 |
+
)
|
273 |
+
elif self.status["answered"]:
|
274 |
+
display_message.append(("class:answermark", self._amark))
|
275 |
+
display_message.append(
|
276 |
+
(
|
277 |
+
"class:answered_question",
|
278 |
+
"%s%s" % (" " if self._amark else "", self._message),
|
279 |
+
)
|
280 |
+
)
|
281 |
+
display_message.append(
|
282 |
+
post_answer
|
283 |
+
if not self._transformer
|
284 |
+
else (
|
285 |
+
"class:answer",
|
286 |
+
" %s" % self._transformer(self.status["result"]),
|
287 |
+
)
|
288 |
+
)
|
289 |
+
else:
|
290 |
+
display_message.append(("class:questionmark", self._qmark))
|
291 |
+
display_message.append(
|
292 |
+
(
|
293 |
+
"class:question",
|
294 |
+
"%s%s" % (" " if self._qmark else "", self._message),
|
295 |
+
)
|
296 |
+
)
|
297 |
+
display_message.append(pre_answer)
|
298 |
+
return display_message
|
299 |
+
|
300 |
+
@abstractmethod
|
301 |
+
def _run(self) -> Any:
|
302 |
+
"""Abstractmethod to enforce a run function is implemented.
|
303 |
+
|
304 |
+
All prompt instance requires a `_run` call to initialise and run an instance of
|
305 |
+
`PromptSession` or `Application`.
|
306 |
+
"""
|
307 |
+
pass
|
308 |
+
|
309 |
+
@abstractmethod
|
310 |
+
async def _run_async(self) -> Any:
|
311 |
+
"""Abstractmethod to enforce a run function is implemented.
|
312 |
+
|
313 |
+
All prompt instance requires a `_run_async` call to initialise and run an instance of
|
314 |
+
`PromptSession` or `Application`.
|
315 |
+
"""
|
316 |
+
pass
|
317 |
+
|
318 |
+
def execute(self, raise_keyboard_interrupt: Optional[bool] = None) -> Any:
|
319 |
+
"""Run the prompt and get the result.
|
320 |
+
|
321 |
+
Args:
|
322 |
+
raise_keyboard_interrupt: **Deprecated**. Set this parameter on the prompt initialisation instead.
|
323 |
+
|
324 |
+
Returns:
|
325 |
+
Value of the user answer. Types varies depending on the prompt.
|
326 |
+
|
327 |
+
Raises:
|
328 |
+
KeyboardInterrupt: When `ctrl-c` is pressed and `raise_keyboard_interrupt` is True.
|
329 |
+
"""
|
330 |
+
result = self._run()
|
331 |
+
if raise_keyboard_interrupt is not None:
|
332 |
+
self._raise_kbi = not os.getenv(
|
333 |
+
"INQUIRERPY_NO_RAISE_KBI", not raise_keyboard_interrupt
|
334 |
+
)
|
335 |
+
if result == INQUIRERPY_KEYBOARD_INTERRUPT:
|
336 |
+
raise KeyboardInterrupt
|
337 |
+
if not self._filter:
|
338 |
+
return result
|
339 |
+
return self._filter(result)
|
340 |
+
|
341 |
+
async def execute_async(self) -> None:
|
342 |
+
"""Run the prompt asynchronously and get the result.
|
343 |
+
|
344 |
+
Returns:
|
345 |
+
Value of the user answer. Types varies depending on the prompt.
|
346 |
+
|
347 |
+
Raises:
|
348 |
+
KeyboardInterrupt: When `ctrl-c` is pressed and `raise_keyboard_interrupt` is True.
|
349 |
+
"""
|
350 |
+
result = await self._run_async()
|
351 |
+
if result == INQUIRERPY_KEYBOARD_INTERRUPT:
|
352 |
+
raise KeyboardInterrupt
|
353 |
+
if not self._filter:
|
354 |
+
return result
|
355 |
+
return self._filter(result)
|
356 |
+
|
357 |
+
@property
|
358 |
+
def instruction(self) -> str:
|
359 |
+
"""str: Instruction to display next to question."""
|
360 |
+
return self._instruction
|
361 |
+
|
362 |
+
@property
|
363 |
+
def kb_maps(self) -> Dict[str, Any]:
|
364 |
+
"""Dict[str, Any]: Keybinding mappings."""
|
365 |
+
return self._kb_maps
|
366 |
+
|
367 |
+
@kb_maps.setter
|
368 |
+
def kb_maps(self, value: Dict[str, Any]) -> None:
|
369 |
+
self._kb_maps = {**self._kb_maps, **value}
|
370 |
+
|
371 |
+
@property
|
372 |
+
def kb_func_lookup(self) -> Dict[str, Any]:
|
373 |
+
"""Dict[str, Any]: Keybinding function lookup mappings.."""
|
374 |
+
return self._kb_func_lookup
|
375 |
+
|
376 |
+
@kb_func_lookup.setter
|
377 |
+
def kb_func_lookup(self, value: Dict[str, Any]) -> None:
|
378 |
+
self._kb_func_lookup = {**self._kb_func_lookup, **value}
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
from .spinner import SpinnerWindow
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/__init__.cpython-310.pyc
ADDED
Binary file (248 Bytes). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/instruction.cpython-310.pyc
ADDED
Binary file (1.74 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/message.cpython-310.pyc
ADDED
Binary file (1.78 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/spinner.cpython-310.pyc
ADDED
Binary file (4.56 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/__pycache__/validation.cpython-310.pyc
ADDED
Binary file (2.38 kB). View file
|
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/instruction.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Module contains :class:`.InstructionWindow` which can be used to display long instructions."""
|
2 |
+
|
3 |
+
from typing import TYPE_CHECKING
|
4 |
+
|
5 |
+
from prompt_toolkit.layout.containers import ConditionalContainer, Window
|
6 |
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
7 |
+
|
8 |
+
if TYPE_CHECKING:
|
9 |
+
from prompt_toolkit.filters.base import FilterOrBool
|
10 |
+
from prompt_toolkit.formatted_text.base import AnyFormattedText
|
11 |
+
|
12 |
+
|
13 |
+
class InstructionWindow(ConditionalContainer):
|
14 |
+
"""Conditional `prompt_toolkit` :class:`~prompt_toolkit.layout.Window` that displays long instructions.
|
15 |
+
|
16 |
+
Args:
|
17 |
+
message: Long instructions to display.
|
18 |
+
filter: Condition to display the instruction window.
|
19 |
+
"""
|
20 |
+
|
21 |
+
def __init__(self, message: str, filter: "FilterOrBool", **kwargs) -> None:
|
22 |
+
self._message = message
|
23 |
+
super().__init__(
|
24 |
+
Window(
|
25 |
+
FormattedTextControl(text=self._get_message),
|
26 |
+
dont_extend_height=True,
|
27 |
+
**kwargs
|
28 |
+
),
|
29 |
+
filter=filter,
|
30 |
+
)
|
31 |
+
|
32 |
+
def _get_message(self) -> "AnyFormattedText":
|
33 |
+
"""Get long instruction to display.
|
34 |
+
|
35 |
+
Returns:
|
36 |
+
FormattedText in list of tuple format.
|
37 |
+
"""
|
38 |
+
return [("class:long_instruction", self._message)]
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/message.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Module contains the main message window :class:`~prompt_toolkit.container.Container`."""
|
2 |
+
|
3 |
+
from typing import TYPE_CHECKING
|
4 |
+
|
5 |
+
from prompt_toolkit.layout.containers import ConditionalContainer, Window
|
6 |
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
7 |
+
from prompt_toolkit.layout.dimension import LayoutDimension
|
8 |
+
|
9 |
+
if TYPE_CHECKING:
|
10 |
+
from prompt_toolkit.filters.base import FilterOrBool
|
11 |
+
from prompt_toolkit.formatted_text.base import AnyFormattedText
|
12 |
+
|
13 |
+
|
14 |
+
class MessageWindow(ConditionalContainer):
|
15 |
+
"""Main window to display question to the user.
|
16 |
+
|
17 |
+
Args:
|
18 |
+
message: The message to display in the terminal.
|
19 |
+
filter: Condition that this message window should be displayed.
|
20 |
+
Use a loading condition to only display this window while its not loading.
|
21 |
+
wrap_lines: Enable line wrapping if the message is too long.
|
22 |
+
show_cursor: Display cursor.
|
23 |
+
"""
|
24 |
+
|
25 |
+
def __init__(
|
26 |
+
self,
|
27 |
+
message: "AnyFormattedText",
|
28 |
+
filter: "FilterOrBool",
|
29 |
+
wrap_lines: bool = True,
|
30 |
+
show_cursor: bool = True,
|
31 |
+
**kwargs
|
32 |
+
) -> None:
|
33 |
+
super().__init__(
|
34 |
+
content=Window(
|
35 |
+
height=LayoutDimension.exact(1) if not wrap_lines else None,
|
36 |
+
content=FormattedTextControl(message, show_cursor=show_cursor),
|
37 |
+
wrap_lines=wrap_lines,
|
38 |
+
dont_extend_height=True,
|
39 |
+
**kwargs
|
40 |
+
),
|
41 |
+
filter=filter,
|
42 |
+
)
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/spinner.py
ADDED
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Module contains spinner related resources.
|
2 |
+
|
3 |
+
Note:
|
4 |
+
The spinner is not a standalone spinner to run in the terminal
|
5 |
+
but rather a `prompt_toolkit` :class:`~prompt_toolkit.layout.Window` that displays a spinner.
|
6 |
+
|
7 |
+
Use library such as `yaspin <https://github.com/pavdmyt/yaspin>`_ if you need a plain spinner.
|
8 |
+
"""
|
9 |
+
import asyncio
|
10 |
+
from typing import TYPE_CHECKING, Callable, List, NamedTuple, Optional, Tuple, Union
|
11 |
+
|
12 |
+
from prompt_toolkit.filters.utils import to_filter
|
13 |
+
from prompt_toolkit.layout.containers import ConditionalContainer, Window
|
14 |
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
15 |
+
|
16 |
+
if TYPE_CHECKING:
|
17 |
+
from prompt_toolkit.filters.base import Filter
|
18 |
+
|
19 |
+
__all__ = ["SPINNERS", "SpinnerWindow"]
|
20 |
+
|
21 |
+
|
22 |
+
class SPINNERS(NamedTuple):
|
23 |
+
"""Presets of spinner patterns.
|
24 |
+
|
25 |
+
See Also:
|
26 |
+
https://github.com/pavdmyt/yaspin/blob/master/yaspin/data/spinners.json
|
27 |
+
|
28 |
+
This only contains some basic ones thats ready to use. For more patterns, checkout the
|
29 |
+
URL above.
|
30 |
+
|
31 |
+
Examples:
|
32 |
+
>>> from InquirerPy import inquirer
|
33 |
+
>>> from InquirerPy.spinner import SPINNERS
|
34 |
+
>>> inquirer.select(message="", choices=lambda _: [1, 2, 3], spinner_pattern=SPINNERS.dots)
|
35 |
+
"""
|
36 |
+
|
37 |
+
dots = ["β ", "β ", "β Ή", "β Έ", "β Ό", "β ΄", "β ¦", "β §", "β ", "β "]
|
38 |
+
dots2 = ["β£Ύ", "β£½", "β£»", "β’Ώ", "β‘Ώ", "β£", "β£―", "β£·"]
|
39 |
+
line = ["-", "\\", "|", "/"]
|
40 |
+
line2 = ["β ", "-", "β", "β", "β", "-"]
|
41 |
+
pipe = ["β€", "β", "β΄", "β", "β", "β", "β¬", "β"]
|
42 |
+
star = ["βΆ", "βΈ", "βΉ", "βΊ", "βΉ", "β·"]
|
43 |
+
star2 = ["+", "x", "*"]
|
44 |
+
flip = ["_", "_", "_", "-", "`", "`", "'", "Β΄", "-", "_", "_", "_"]
|
45 |
+
hamburger = ["β±", "β²", "β΄"]
|
46 |
+
grow_vertical = ["β", "β", "β", "β
", "β", "β", "β", "β
", "β", "β"]
|
47 |
+
grow_horizontal = ["β", "β", "β", "β", "β", "β", "β", "β", "β", "β", "β", "β"]
|
48 |
+
box_bounce = ["β", "β", "β", "β"]
|
49 |
+
triangle = ["β’", "β£", "β€", "β₯"]
|
50 |
+
arc = ["β", "β ", "β", "β", "β‘", "β"]
|
51 |
+
circle = ["β‘", "β", "β "]
|
52 |
+
|
53 |
+
|
54 |
+
class SpinnerWindow(ConditionalContainer):
|
55 |
+
"""Conditional `prompt_toolkit` :class:`~prompt_toolkit.layout.Window` that displays a spinner.
|
56 |
+
|
57 |
+
Args:
|
58 |
+
loading: A :class:`~prompt_toolkit.filters.Condition` to indicate if the spinner should be visible.
|
59 |
+
redraw: A redraw function (i.e. :meth:`~prompt_toolkit.application.Application.invalidate`) to refresh the UI.
|
60 |
+
pattern: List of pattern to display as the spinner.
|
61 |
+
delay: Spinner refresh frequency.
|
62 |
+
text: Loading text to display.
|
63 |
+
"""
|
64 |
+
|
65 |
+
def __init__(
|
66 |
+
self,
|
67 |
+
loading: "Filter",
|
68 |
+
redraw: Callable[[], None],
|
69 |
+
pattern: Optional[Union[List[str], SPINNERS]] = None,
|
70 |
+
delay: float = 0.1,
|
71 |
+
text: str = "",
|
72 |
+
) -> None:
|
73 |
+
self._loading = to_filter(loading)
|
74 |
+
self._spinning = False
|
75 |
+
self._redraw = redraw
|
76 |
+
self._pattern = pattern or SPINNERS.line
|
77 |
+
self._char = self._pattern[0]
|
78 |
+
self._delay = delay
|
79 |
+
self._text = text or "Loading ..."
|
80 |
+
|
81 |
+
super().__init__(
|
82 |
+
content=Window(content=FormattedTextControl(text=self._get_text)),
|
83 |
+
filter=self._loading,
|
84 |
+
)
|
85 |
+
|
86 |
+
def _get_text(self) -> List[Tuple[str, str]]:
|
87 |
+
"""Dynamically get the text for the :class:`~prompt_toolkit.layout.Window`.
|
88 |
+
|
89 |
+
Returns:
|
90 |
+
Formatted text.
|
91 |
+
"""
|
92 |
+
return [
|
93 |
+
("class:spinner_pattern", self._char),
|
94 |
+
("", " "),
|
95 |
+
("class:spinner_text", self._text),
|
96 |
+
]
|
97 |
+
|
98 |
+
async def start(self) -> None:
|
99 |
+
"""Start the spinner."""
|
100 |
+
if self._spinning:
|
101 |
+
return
|
102 |
+
self._spinning = True
|
103 |
+
while self._loading():
|
104 |
+
for char in self._pattern:
|
105 |
+
await asyncio.sleep(self._delay)
|
106 |
+
self._char = char
|
107 |
+
self._redraw()
|
108 |
+
self._spinning = False
|
tutorial-env/lib/python3.10/site-packages/InquirerPy/containers/validation.py
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Module contains :class:`.ValidationWindow` which can be used to display error."""
|
2 |
+
|
3 |
+
from typing import Optional
|
4 |
+
|
5 |
+
from prompt_toolkit.filters.base import FilterOrBool
|
6 |
+
from prompt_toolkit.formatted_text.base import AnyFormattedText
|
7 |
+
from prompt_toolkit.layout.containers import ConditionalContainer, Float, Window
|
8 |
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
9 |
+
|
10 |
+
|
11 |
+
class ValidationWindow(ConditionalContainer):
|
12 |
+
"""Conditional `prompt_toolkit` :class:`~prompt_toolkit.layout.Window` that displays error.
|
13 |
+
|
14 |
+
Args:
|
15 |
+
invalid_message: Error message to display when error occured.
|
16 |
+
filter: Condition to display the error window.
|
17 |
+
"""
|
18 |
+
|
19 |
+
def __init__(
|
20 |
+
self, invalid_message: AnyFormattedText, filter: FilterOrBool, **kwargs
|
21 |
+
) -> None:
|
22 |
+
super().__init__(
|
23 |
+
Window(
|
24 |
+
FormattedTextControl(invalid_message), dont_extend_height=True, **kwargs
|
25 |
+
),
|
26 |
+
filter=filter,
|
27 |
+
)
|
28 |
+
|
29 |
+
|
30 |
+
class ValidationFloat(Float):
|
31 |
+
""":class:`~prompt_toolkit.layout.Float` wrapper around :class:`.ValidationWindow`.
|
32 |
+
|
33 |
+
Args:
|
34 |
+
invalid_message: Error message to display when error occured.
|
35 |
+
filter: Condition to display the error window.
|
36 |
+
left: Distance to left.
|
37 |
+
right: Distance to right.
|
38 |
+
bottom: Distance to bottom.
|
39 |
+
top: Distance to top.
|
40 |
+
"""
|
41 |
+
|
42 |
+
def __init__(
|
43 |
+
self,
|
44 |
+
invalid_message: AnyFormattedText,
|
45 |
+
filter: FilterOrBool,
|
46 |
+
left: Optional[int] = None,
|
47 |
+
right: Optional[int] = None,
|
48 |
+
bottom: Optional[int] = None,
|
49 |
+
top: Optional[int] = None,
|
50 |
+
**kwargs
|
51 |
+
) -> None:
|
52 |
+
super().__init__(
|
53 |
+
content=ValidationWindow(
|
54 |
+
invalid_message=invalid_message, filter=filter, **kwargs
|
55 |
+
),
|
56 |
+
left=left,
|
57 |
+
right=right,
|
58 |
+
bottom=bottom,
|
59 |
+
top=top,
|
60 |
+
)
|