python-lab-toolkit 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pylab/__init__.py +43 -0
- pylab/cli.py +282 -0
- pylab/data/Data.csv +11 -0
- pylab/data/alphabet_stock_data.csv +143 -0
- pylab/data/breast-cancer.csv +351 -0
- pylab/data/dirtydata.csv +33 -0
- pylab/data/groceries.csv +359 -0
- pylab/data/iris.csv +151 -0
- pylab/data/rainfall.csv +151 -0
- pylab/data/students.csv +7 -0
- pylab/data/winequality-red.csv +1601 -0
- pylab/data/winequality-white.csv +2401 -0
- pylab/datasets.py +277 -0
- pylab/environment.py +136 -0
- pylab/errors.py +53 -0
- pylab/generator.py +216 -0
- pylab/registry.py +562 -0
- pylab/templates/q1/variable_validator.py +43 -0
- pylab/templates/q10/password_strength.py +42 -0
- pylab/templates/q11/recursion_math.py +28 -0
- pylab/templates/q12/main_analyzer.py +46 -0
- pylab/templates/q12/text_analyzer.py +16 -0
- pylab/templates/q12/text_preprocessor.py +15 -0
- pylab/templates/q13/student.py +26 -0
- pylab/templates/q14/circle.py +26 -0
- pylab/templates/q15/employee_salary.py +46 -0
- pylab/templates/q16/smart_calculator.py +51 -0
- pylab/templates/q17/complex_number.py +43 -0
- pylab/templates/q18/vehicle_inheritance.py +43 -0
- pylab/templates/q19/file_word_counter.py +48 -0
- pylab/templates/q19/sample.txt +6 -0
- pylab/templates/q2/single_number.py +26 -0
- pylab/templates/q20/age_validator.py +27 -0
- pylab/templates/q21/transaction_manager.py +45 -0
- pylab/templates/q22/date_formatter.py +30 -0
- pylab/templates/q23/rainfall_analyzer.py +73 -0
- pylab/templates/q24/student_marks.py +58 -0
- pylab/templates/q25/library_manager.py +182 -0
- pylab/templates/q26/mysql_employee_manager.py +239 -0
- pylab/templates/q27/crud_client.py +98 -0
- pylab/templates/q27/mock_server.py +85 -0
- pylab/templates/q28/index.html +33 -0
- pylab/templates/q28/login_handler.py +31 -0
- pylab/templates/q28/server.py +44 -0
- pylab/templates/q29/index.html +50 -0
- pylab/templates/q29/register_handler.py +42 -0
- pylab/templates/q29/server.py +42 -0
- pylab/templates/q3/string_operations.py +32 -0
- pylab/templates/q30/crud_handler.py +60 -0
- pylab/templates/q30/database.py +66 -0
- pylab/templates/q30/index.html +59 -0
- pylab/templates/q30/server.py +51 -0
- pylab/templates/q31/numpy_matrix.py +40 -0
- pylab/templates/q32/numpy_slicing.py +43 -0
- pylab/templates/q33/pandas_students.py +41 -0
- pylab/templates/q34/pandas_salary.py +37 -0
- pylab/templates/q35/sales_barchart.py +58 -0
- pylab/templates/q36/weather_plot.py +50 -0
- pylab/templates/q37/age_categorization.py +38 -0
- pylab/templates/q38/concat_rows.py +38 -0
- pylab/templates/q39/concat_cols.py +38 -0
- pylab/templates/q4/menu_string_processor.py +68 -0
- pylab/templates/q40/concat_merge.py +44 -0
- pylab/templates/q41/pandas_joins.py +46 -0
- pylab/templates/q42/groupby_school.py +32 -0
- pylab/templates/q43/groupby_multi.py +29 -0
- pylab/templates/q44/alphabet_stock_viz.py +95 -0
- pylab/templates/q45/multi_plot.py +65 -0
- pylab/templates/q46/dataframe_barchart.py +60 -0
- pylab/templates/q47/preprocess_data.py +54 -0
- pylab/templates/q48/clean_dirtydata.py +62 -0
- pylab/templates/q49/wine_regression.py +169 -0
- pylab/templates/q5/phonebook.py +105 -0
- pylab/templates/q50/breast_cancer_classifier.py +147 -0
- pylab/templates/q51/iris_clustering.py +95 -0
- pylab/templates/q52/apriori_groceries.py +88 -0
- pylab/templates/q6/calculator.py +67 -0
- pylab/templates/q7/session_attendees.py +37 -0
- pylab/templates/q8/number_properties.py +68 -0
- pylab/templates/q9/greet_people.py +26 -0
- python_lab_toolkit-1.0.0.dist-info/LICENSE +21 -0
- python_lab_toolkit-1.0.0.dist-info/METADATA +427 -0
- python_lab_toolkit-1.0.0.dist-info/RECORD +86 -0
- python_lab_toolkit-1.0.0.dist-info/WHEEL +5 -0
- python_lab_toolkit-1.0.0.dist-info/entry_points.txt +2 -0
- python_lab_toolkit-1.0.0.dist-info/top_level.txt +1 -0
pylab/__init__.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""python-lab-toolkit (pylab): Beginner-friendly lab generator and toolkit for 52 Python practicals."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.0.0"
|
|
4
|
+
__author__ = "Python Lab Toolkit Developers"
|
|
5
|
+
__license__ = "MIT"
|
|
6
|
+
|
|
7
|
+
from pylab.datasets import acquire_dataset, list_datasets
|
|
8
|
+
from pylab.environment import run_doctor
|
|
9
|
+
from pylab.errors import (
|
|
10
|
+
DatasetDownloadError,
|
|
11
|
+
DatasetValidationError,
|
|
12
|
+
DependencyMissingError,
|
|
13
|
+
FileCollisionError,
|
|
14
|
+
PyLabError,
|
|
15
|
+
QuestionNotFoundError,
|
|
16
|
+
)
|
|
17
|
+
from pylab.generator import generate_all, generate_category, generate_project
|
|
18
|
+
from pylab.registry import (
|
|
19
|
+
QUESTION_LIST,
|
|
20
|
+
get_categories,
|
|
21
|
+
get_question,
|
|
22
|
+
get_questions_by_category,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"__version__",
|
|
27
|
+
"generate_project",
|
|
28
|
+
"generate_category",
|
|
29
|
+
"generate_all",
|
|
30
|
+
"get_question",
|
|
31
|
+
"get_categories",
|
|
32
|
+
"get_questions_by_category",
|
|
33
|
+
"acquire_dataset",
|
|
34
|
+
"list_datasets",
|
|
35
|
+
"run_doctor",
|
|
36
|
+
"PyLabError",
|
|
37
|
+
"QuestionNotFoundError",
|
|
38
|
+
"FileCollisionError",
|
|
39
|
+
"DatasetDownloadError",
|
|
40
|
+
"DatasetValidationError",
|
|
41
|
+
"DependencyMissingError",
|
|
42
|
+
"QUESTION_LIST",
|
|
43
|
+
]
|
pylab/cli.py
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"""Beginner-friendly Command Line Interface for python-lab-toolkit."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import os
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
from pylab import __version__
|
|
10
|
+
from pylab.datasets import list_datasets
|
|
11
|
+
from pylab.environment import run_doctor
|
|
12
|
+
from pylab.errors import FileCollisionError, PyLabError, QuestionNotFoundError
|
|
13
|
+
from pylab.generator import generate_all, generate_category, generate_project
|
|
14
|
+
from pylab.registry import QUESTION_LIST, get_categories, get_question, get_questions_by_category
|
|
15
|
+
|
|
16
|
+
def format_question_summary(q) -> str:
|
|
17
|
+
deps = f" [Needs: {', '.join(q.dependencies)}]" if q.dependencies else ""
|
|
18
|
+
datasets = f" [Data: {', '.join(q.datasets)}]" if q.datasets else ""
|
|
19
|
+
return f" Q{q.number:<2} : {q.title:<46} ({q.category}){deps}{datasets}"
|
|
20
|
+
|
|
21
|
+
def cmd_list(args) -> int:
|
|
22
|
+
category = getattr(args, "category", None)
|
|
23
|
+
if category:
|
|
24
|
+
norm_cat = category.strip().lower()
|
|
25
|
+
if norm_cat in ("database", "db"):
|
|
26
|
+
norm_cat = "databases"
|
|
27
|
+
questions = get_questions_by_category(norm_cat)
|
|
28
|
+
if not questions:
|
|
29
|
+
avail = ", ".join(get_categories())
|
|
30
|
+
print(f"No questions found for category '{category}'. Available categories: {avail}")
|
|
31
|
+
return 1
|
|
32
|
+
print(f"\nPython Lab Questions in Category '{norm_cat}' ({len(questions)} items):")
|
|
33
|
+
print("=" * 80)
|
|
34
|
+
for q in questions:
|
|
35
|
+
print(format_question_summary(q))
|
|
36
|
+
print("=" * 80)
|
|
37
|
+
return 0
|
|
38
|
+
|
|
39
|
+
print(f"\nPython Lab Toolkit - Complete Question Registry ({len(QUESTION_LIST)} questions):")
|
|
40
|
+
print("=" * 84)
|
|
41
|
+
current_cat = None
|
|
42
|
+
for q in QUESTION_LIST:
|
|
43
|
+
if q.category != current_cat:
|
|
44
|
+
current_cat = q.category
|
|
45
|
+
print(f"\n-- {current_cat.upper()} --")
|
|
46
|
+
print(format_question_summary(q))
|
|
47
|
+
print("=" * 84)
|
|
48
|
+
print("\nTo generate a project, type: pylab q<number>")
|
|
49
|
+
print("Example: pylab q12 or pylab q49")
|
|
50
|
+
print("To auto-generate and immediately run a lab: pylab run q25\n")
|
|
51
|
+
return 0
|
|
52
|
+
|
|
53
|
+
def cmd_datasets(args) -> int:
|
|
54
|
+
data_list = list_datasets()
|
|
55
|
+
print("\nPython Lab Toolkit - Dataset Registry:")
|
|
56
|
+
print("=" * 88)
|
|
57
|
+
print(f"{'Dataset Filename':<26} | {'Used In':<12} | {'Bundled':<10} | {'Description'}")
|
|
58
|
+
print("-" * 88)
|
|
59
|
+
for d in data_list:
|
|
60
|
+
q_str = ", ".join(f"Q{q}" for q in d["questions"])
|
|
61
|
+
b_str = "YES (Offline)" if d["bundled"] else "Remote Only"
|
|
62
|
+
print(f"{d['name']:<26} | {q_str:<12} | {b_str:<10} | {d['description']}")
|
|
63
|
+
print("=" * 88)
|
|
64
|
+
print("All bundled datasets are included inside the package and work without internet access.\n")
|
|
65
|
+
return 0
|
|
66
|
+
|
|
67
|
+
def cmd_generate_question(q_identifier: any, force: bool = False, offline: bool = False, out_dir: str = ".") -> int:
|
|
68
|
+
try:
|
|
69
|
+
res = generate_project(q_identifier, target_base_dir=out_dir, force=force, offline=offline)
|
|
70
|
+
print(res.message)
|
|
71
|
+
return 0
|
|
72
|
+
except FileCollisionError as col_err:
|
|
73
|
+
print(f"\n{col_err}")
|
|
74
|
+
return 1
|
|
75
|
+
except QuestionNotFoundError as q_err:
|
|
76
|
+
print(f"\n{q_err}")
|
|
77
|
+
return 1
|
|
78
|
+
except Exception as e:
|
|
79
|
+
print(f"\nError: {e}")
|
|
80
|
+
return 1
|
|
81
|
+
|
|
82
|
+
def cmd_run(args) -> int:
|
|
83
|
+
q_spec = get_question(args.question)
|
|
84
|
+
if not q_spec:
|
|
85
|
+
print(f"Question '{args.question}' was not recognized.")
|
|
86
|
+
return 1
|
|
87
|
+
|
|
88
|
+
project_dir = os.path.join(args.output_dir, q_spec.slug)
|
|
89
|
+
if not os.path.isdir(project_dir):
|
|
90
|
+
print(f"Project for Question {q_spec.number} not found locally. Auto-generating now...")
|
|
91
|
+
generate_project(q_spec.number, target_base_dir=args.output_dir, offline=args.offline)
|
|
92
|
+
|
|
93
|
+
entry_file = os.path.join(project_dir, q_spec.entry_point)
|
|
94
|
+
if not os.path.isfile(entry_file):
|
|
95
|
+
print(f"Entry script '{entry_file}' not found.")
|
|
96
|
+
return 1
|
|
97
|
+
|
|
98
|
+
print(f"Executing Question {q_spec.number} ({q_spec.title}) automatically...\n")
|
|
99
|
+
proc = subprocess.run([sys.executable, q_spec.entry_point], cwd=project_dir)
|
|
100
|
+
return proc.returncode
|
|
101
|
+
|
|
102
|
+
def cmd_category(args) -> int:
|
|
103
|
+
category = args.name.strip().lower()
|
|
104
|
+
if category in ("database", "db"):
|
|
105
|
+
category = "databases"
|
|
106
|
+
questions = get_questions_by_category(category)
|
|
107
|
+
if not questions:
|
|
108
|
+
avail = ", ".join(get_categories())
|
|
109
|
+
print(f"Unknown category '{category}'. Available categories: {avail}")
|
|
110
|
+
return 1
|
|
111
|
+
|
|
112
|
+
print(f"Generating all {len(questions)} questions in category '{category}'...")
|
|
113
|
+
success_count = 0
|
|
114
|
+
for q in questions:
|
|
115
|
+
try:
|
|
116
|
+
res = generate_project(q.number, target_base_dir=args.output_dir, force=args.force, offline=args.offline)
|
|
117
|
+
print(f" [OK] Question {q.number}: {res.project_dir}/")
|
|
118
|
+
success_count += 1
|
|
119
|
+
except FileCollisionError:
|
|
120
|
+
print(f" [SKIP] Question {q.number} ({q.slug}) already exists. Use --force to replace.")
|
|
121
|
+
except Exception as err:
|
|
122
|
+
print(f" [FAIL] Question {q.number}: {err}")
|
|
123
|
+
print(f"\nCompleted: {success_count} of {len(questions)} projects generated.")
|
|
124
|
+
return 0
|
|
125
|
+
|
|
126
|
+
def cmd_all(args) -> int:
|
|
127
|
+
total_q = len(QUESTION_LIST)
|
|
128
|
+
if not args.yes:
|
|
129
|
+
print(f"Generating all {total_q} lab questions will create {total_q} dedicated project directories.")
|
|
130
|
+
answer = input("Do you wish to continue? (y/N): ").strip().lower()
|
|
131
|
+
if answer not in ("y", "yes"):
|
|
132
|
+
print("Operation cancelled.")
|
|
133
|
+
return 0
|
|
134
|
+
|
|
135
|
+
print(f"\nGenerating all {total_q} questions...")
|
|
136
|
+
success_count = 0
|
|
137
|
+
skipped_count = 0
|
|
138
|
+
for q in QUESTION_LIST:
|
|
139
|
+
try:
|
|
140
|
+
res = generate_project(q.number, target_base_dir=args.output_dir, force=args.force, offline=args.offline)
|
|
141
|
+
print(f" [OK] Q{q.number:<2} -> {res.project_dir}/")
|
|
142
|
+
success_count += 1
|
|
143
|
+
except FileCollisionError:
|
|
144
|
+
print(f" [SKIP] Q{q.number:<2} ({q.slug}) exists (use --force to overwrite)")
|
|
145
|
+
skipped_count += 1
|
|
146
|
+
except Exception as err:
|
|
147
|
+
print(f" [FAIL] Q{q.number:<2}: {err}")
|
|
148
|
+
|
|
149
|
+
print(f"\nSummary: {success_count} generated, {skipped_count} skipped.")
|
|
150
|
+
return 0
|
|
151
|
+
|
|
152
|
+
def cmd_install_deps(args) -> int:
|
|
153
|
+
q_spec = get_question(args.question)
|
|
154
|
+
if not q_spec:
|
|
155
|
+
print(f"Question '{args.question}' not recognized.")
|
|
156
|
+
return 1
|
|
157
|
+
|
|
158
|
+
if not q_spec.dependencies:
|
|
159
|
+
print(f"Question {q_spec.number} requires only Python standard library. No additional packages needed.")
|
|
160
|
+
return 0
|
|
161
|
+
|
|
162
|
+
deps = q_spec.dependencies
|
|
163
|
+
print(f"Question {q_spec.number} ({q_spec.title}) requires: {', '.join(deps)}")
|
|
164
|
+
if not args.yes:
|
|
165
|
+
ans = input(f"Install {', '.join(deps)} using pip now? (y/N): ").strip().lower()
|
|
166
|
+
if ans not in ("y", "yes"):
|
|
167
|
+
print("Installation cancelled.")
|
|
168
|
+
return 0
|
|
169
|
+
|
|
170
|
+
cmd = [sys.executable, "-m", "pip", "install"] + deps
|
|
171
|
+
print(f"Running: {' '.join(cmd)}")
|
|
172
|
+
result = subprocess.run(cmd)
|
|
173
|
+
return result.returncode
|
|
174
|
+
|
|
175
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
176
|
+
parser = argparse.ArgumentParser(
|
|
177
|
+
prog="pylab",
|
|
178
|
+
description="python-lab-toolkit: Beginner-friendly CLI for 52 Python lab solutions with automated datasets.",
|
|
179
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
180
|
+
)
|
|
181
|
+
parser.add_argument("-v", "--version", action="store_true", help="Show package version and exit")
|
|
182
|
+
|
|
183
|
+
subparsers = parser.add_subparsers(dest="command", help="Available subcommands")
|
|
184
|
+
|
|
185
|
+
list_p = subparsers.add_parser("list", help="List all 52 questions or filter by category")
|
|
186
|
+
list_p.add_argument("--category", "-c", type=str, help="Filter by category (e.g. numpy, pandas, databases, machine-learning)")
|
|
187
|
+
|
|
188
|
+
subparsers.add_parser("doctor", help="Check Python version, write permissions, and optional dependencies")
|
|
189
|
+
subparsers.add_parser("datasets", help="Display all registered and bundled datasets")
|
|
190
|
+
subparsers.add_parser("version", help="Show version information")
|
|
191
|
+
|
|
192
|
+
run_p = subparsers.add_parser("run", help="Auto-generate and execute a lab question immediately")
|
|
193
|
+
run_p.add_argument("question", type=str, help="Question number or identifier (e.g. q25, q26, or 25)")
|
|
194
|
+
run_p.add_argument("--offline", action="store_true", help="Force offline bundled datasets")
|
|
195
|
+
run_p.add_argument("--output-dir", "-o", default=".", help="Directory where project is located or generated")
|
|
196
|
+
|
|
197
|
+
cat_p = subparsers.add_parser("category", help="Generate all questions in a specific category")
|
|
198
|
+
cat_p.add_argument("name", type=str, help="Category name (e.g. numpy, pandas, databases, machine-learning)")
|
|
199
|
+
cat_p.add_argument("--force", "-f", action="store_true", help="Overwrite existing project files")
|
|
200
|
+
cat_p.add_argument("--offline", action="store_true", help="Force offline bundled datasets")
|
|
201
|
+
cat_p.add_argument("--output-dir", "-o", default=".", help="Directory where projects will be generated")
|
|
202
|
+
|
|
203
|
+
all_p = subparsers.add_parser("all", help="Generate all 52 lab questions")
|
|
204
|
+
all_p.add_argument("--yes", "-y", action="store_true", help="Confirm generation without interactive prompt")
|
|
205
|
+
all_p.add_argument("--force", "-f", action="store_true", help="Overwrite existing project files")
|
|
206
|
+
all_p.add_argument("--offline", action="store_true", help="Force offline bundled datasets")
|
|
207
|
+
all_p.add_argument("--output-dir", "-o", default=".", help="Directory where projects will be generated")
|
|
208
|
+
|
|
209
|
+
deps_p = subparsers.add_parser("install-deps", help="Install third-party dependencies required for a question")
|
|
210
|
+
deps_p.add_argument("question", type=str, help="Question number or identifier (e.g. q49 or 49)")
|
|
211
|
+
deps_p.add_argument("--yes", "-y", action="store_true", help="Confirm installation without prompting")
|
|
212
|
+
|
|
213
|
+
gen_p = subparsers.add_parser("generate", help="Generate project files for a specific question")
|
|
214
|
+
gen_p.add_argument("question", type=str, help="Question number (1-52)")
|
|
215
|
+
gen_p.add_argument("--force", "-f", action="store_true", help="Overwrite existing project files")
|
|
216
|
+
gen_p.add_argument("--offline", action="store_true", help="Force offline bundled datasets")
|
|
217
|
+
gen_p.add_argument("--output-dir", "-o", default=".", help="Directory where project will be generated")
|
|
218
|
+
|
|
219
|
+
return parser
|
|
220
|
+
|
|
221
|
+
def main(argv: Optional[List[str]] = None) -> int:
|
|
222
|
+
if argv is None:
|
|
223
|
+
argv = sys.argv[1:]
|
|
224
|
+
|
|
225
|
+
if not argv:
|
|
226
|
+
parser = build_parser()
|
|
227
|
+
parser.print_help()
|
|
228
|
+
return 0
|
|
229
|
+
|
|
230
|
+
first_arg = argv[0].strip().lower()
|
|
231
|
+
|
|
232
|
+
if first_arg in ("--version", "-v", "version"):
|
|
233
|
+
print(f"python-lab-toolkit (pylab) v{__version__}")
|
|
234
|
+
return 0
|
|
235
|
+
|
|
236
|
+
if first_arg.startswith("q") and first_arg[1:].isdigit():
|
|
237
|
+
q_num = int(first_arg[1:])
|
|
238
|
+
gen_parser = argparse.ArgumentParser(prog=f"pylab {first_arg}")
|
|
239
|
+
gen_parser.add_argument("--force", "-f", action="store_true", help="Overwrite existing files")
|
|
240
|
+
gen_parser.add_argument("--offline", action="store_true", help="Force offline bundled datasets")
|
|
241
|
+
gen_parser.add_argument("--output-dir", "-o", default=".", help="Output directory")
|
|
242
|
+
parsed_opts = gen_parser.parse_args(argv[1:])
|
|
243
|
+
return cmd_generate_question(
|
|
244
|
+
q_num,
|
|
245
|
+
force=parsed_opts.force,
|
|
246
|
+
offline=parsed_opts.offline,
|
|
247
|
+
out_dir=parsed_opts.output_dir,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
parser = build_parser()
|
|
251
|
+
args = parser.parse_args(argv)
|
|
252
|
+
|
|
253
|
+
if args.version or args.command == "version":
|
|
254
|
+
print(f"python-lab-toolkit (pylab) v{__version__}")
|
|
255
|
+
return 0
|
|
256
|
+
elif args.command == "list":
|
|
257
|
+
return cmd_list(args)
|
|
258
|
+
elif args.command == "doctor":
|
|
259
|
+
return run_doctor()
|
|
260
|
+
elif args.command == "datasets":
|
|
261
|
+
return cmd_datasets(args)
|
|
262
|
+
elif args.command == "run":
|
|
263
|
+
return cmd_run(args)
|
|
264
|
+
elif args.command == "category":
|
|
265
|
+
return cmd_category(args)
|
|
266
|
+
elif args.command == "all":
|
|
267
|
+
return cmd_all(args)
|
|
268
|
+
elif args.command == "install-deps":
|
|
269
|
+
return cmd_install_deps(args)
|
|
270
|
+
elif args.command == "generate":
|
|
271
|
+
return cmd_generate_question(
|
|
272
|
+
args.question,
|
|
273
|
+
force=args.force,
|
|
274
|
+
offline=args.offline,
|
|
275
|
+
out_dir=args.output_dir,
|
|
276
|
+
)
|
|
277
|
+
else:
|
|
278
|
+
parser.print_help()
|
|
279
|
+
return 0
|
|
280
|
+
|
|
281
|
+
if __name__ == "__main__":
|
|
282
|
+
sys.exit(main())
|
pylab/data/Data.csv
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Date,Open,High,Low,Close,Adj Close,Volume
|
|
2
|
+
2020-04-01,1203.0,1240.43,1194.27,1232.73,1232.73,1707528
|
|
3
|
+
2020-04-02,1224.01,1226.28,1203.44,1212.64,1212.64,2123658
|
|
4
|
+
2020-04-03,1216.8,1219.57,1189.32,1192.2,1192.2,1331755
|
|
5
|
+
2020-04-06,1183.62,1210.99,1172.92,1205.9,1205.9,2098574
|
|
6
|
+
2020-04-07,1210.37,1228.5,1200.88,1215.03,1215.03,2219204
|
|
7
|
+
2020-04-08,1221.18,1243.81,1217.92,1239.33,1239.33,3007959
|
|
8
|
+
2020-04-09,1237.55,1250.78,1229.34,1232.04,1232.04,1612794
|
|
9
|
+
2020-04-10,1236.6,1249.01,1211.51,1214.93,1214.93,2003587
|
|
10
|
+
2020-04-13,1213.9,1221.38,1193.74,1199.36,1199.36,2247764
|
|
11
|
+
2020-04-14,1190.87,1226.47,1177.74,1213.97,1213.97,1610658
|
|
12
|
+
2020-04-15,1223.96,1236.83,1187.14,1201.74,1201.74,2191447
|
|
13
|
+
2020-04-16,1201.45,1206.23,1178.39,1185.6,1185.6,1445934
|
|
14
|
+
2020-04-17,1175.64,1182.72,1145.66,1159.7,1159.7,3108443
|
|
15
|
+
2020-04-20,1163.63,1175.13,1142.14,1154.32,1154.32,3241247
|
|
16
|
+
2020-04-21,1150.25,1164.84,1124.23,1133.76,1133.76,3474131
|
|
17
|
+
2020-04-22,1130.03,1132.68,1100.18,1108.38,1108.38,3427704
|
|
18
|
+
2020-04-23,1117.6,1120.64,1096.84,1101.26,1101.26,1485048
|
|
19
|
+
2020-04-24,1095.96,1111.66,1082.39,1108.1,1108.1,2232702
|
|
20
|
+
2020-04-27,1098.89,1108.8,1088.34,1105.73,1105.73,3392709
|
|
21
|
+
2020-04-28,1100.95,1111.66,1087.27,1093.35,1093.35,2314068
|
|
22
|
+
2020-04-29,1096.78,1102.68,1087.44,1093.55,1093.55,1504267
|
|
23
|
+
2020-04-30,1095.97,1105.29,1068.18,1071.48,1071.48,3455002
|
|
24
|
+
2020-05-01,1066.78,1080.91,1040.05,1053.5,1053.5,2224603
|
|
25
|
+
2020-05-04,1046.65,1059.49,1030.82,1041.97,1041.97,3418538
|
|
26
|
+
2020-05-05,1048.31,1054.2,1013.12,1023.74,1023.74,1763257
|
|
27
|
+
2020-05-06,1031.53,1043.18,1017.06,1021.08,1021.08,2381771
|
|
28
|
+
2020-05-07,1025.43,1038.35,1015.18,1033.7,1033.7,2307228
|
|
29
|
+
2020-05-08,1028.72,1045.33,1026.06,1031.52,1031.52,2976605
|
|
30
|
+
2020-05-11,1022.4,1049.35,1018.7,1043.01,1043.01,2298720
|
|
31
|
+
2020-05-12,1041.85,1053.02,1016.45,1025.74,1025.74,1669233
|
|
32
|
+
2020-05-13,1033.4,1047.15,1003.45,1012.54,1012.54,2748604
|
|
33
|
+
2020-05-14,1005.5,1016.2,999.49,1012.54,1012.54,1367331
|
|
34
|
+
2020-05-15,1006.74,1036.42,1003.4,1031.18,1031.18,2904470
|
|
35
|
+
2020-05-18,1036.17,1078.76,1031.09,1064.73,1064.73,1881581
|
|
36
|
+
2020-05-19,1070.95,1113.1,1068.63,1099.64,1099.64,2593286
|
|
37
|
+
2020-05-20,1097.87,1126.61,1086.31,1115.9,1115.9,2240888
|
|
38
|
+
2020-05-21,1121.65,1125.06,1097.98,1111.32,1111.32,3174217
|
|
39
|
+
2020-05-22,1117.65,1125.63,1098.91,1104.88,1104.88,2154604
|
|
40
|
+
2020-05-25,1108.08,1115.26,1089.72,1095.34,1095.34,1491171
|
|
41
|
+
2020-05-26,1090.92,1129.44,1083.72,1119.1,1119.1,3449051
|
|
42
|
+
2020-05-27,1109.65,1123.05,1097.46,1102.86,1102.86,2313446
|
|
43
|
+
2020-05-28,1104.79,1111.28,1069.67,1081.89,1081.89,3030368
|
|
44
|
+
2020-05-29,1082.12,1097.47,1072.62,1090.46,1090.46,2268383
|
|
45
|
+
2020-06-01,1089.18,1097.94,1054.14,1066.62,1066.62,2026425
|
|
46
|
+
2020-06-02,1058.02,1068.66,1046.76,1053.05,1053.05,2516657
|
|
47
|
+
2020-06-03,1045.54,1070.73,1036.95,1057.03,1057.03,2912924
|
|
48
|
+
2020-06-04,1060.97,1070.18,1049.42,1053.91,1053.91,2790250
|
|
49
|
+
2020-06-05,1061.97,1084.22,1056.06,1074.22,1074.22,3498215
|
|
50
|
+
2020-06-08,1070.3,1095.88,1058.09,1091.15,1091.15,2551611
|
|
51
|
+
2020-06-09,1089.99,1095.34,1081.84,1090.56,1090.56,1911737
|
|
52
|
+
2020-06-10,1086.24,1108.11,1076.19,1097.48,1097.48,1591694
|
|
53
|
+
2020-06-11,1102.5,1133.26,1097.58,1122.51,1122.51,2035211
|
|
54
|
+
2020-06-12,1113.43,1128.22,1086.58,1096.53,1096.53,1505463
|
|
55
|
+
2020-06-15,1104.25,1113.78,1092.91,1104.3,1104.3,2810522
|
|
56
|
+
2020-06-16,1099.18,1111.9,1097.11,1101.37,1101.37,1647059
|
|
57
|
+
2020-06-17,1095.75,1126.01,1084.7,1113.56,1113.56,3148463
|
|
58
|
+
2020-06-18,1108.54,1121.57,1078.37,1086.3,1086.3,3148854
|
|
59
|
+
2020-06-19,1096.06,1117.52,1081.71,1107.78,1107.78,3056287
|
|
60
|
+
2020-06-22,1112.17,1129.43,1099.37,1120.87,1120.87,3497941
|
|
61
|
+
2020-06-23,1114.05,1127.25,1105.73,1113.58,1113.58,2236998
|
|
62
|
+
2020-06-24,1109.13,1142.43,1100.83,1130.32,1130.32,2203469
|
|
63
|
+
2020-06-25,1121.87,1127.58,1106.44,1111.97,1111.97,2540959
|
|
64
|
+
2020-06-26,1103.58,1131.66,1096.6,1127.7,1127.7,1840911
|
|
65
|
+
2020-06-29,1118.98,1140.13,1109.93,1132.83,1132.83,2943883
|
|
66
|
+
2020-06-30,1139.49,1146.55,1105.9,1117.91,1117.91,1281922
|
|
67
|
+
2020-07-01,1123.22,1152.28,1121.14,1145.34,1145.34,2675383
|
|
68
|
+
2020-07-02,1143.14,1156.73,1121.7,1134.56,1134.56,3457460
|
|
69
|
+
2020-07-03,1135.48,1161.43,1130.61,1151.59,1151.59,2120321
|
|
70
|
+
2020-07-06,1151.3,1158.36,1130.61,1141.31,1141.31,2895827
|
|
71
|
+
2020-07-07,1148.12,1176.9,1133.37,1162.95,1162.95,3440276
|
|
72
|
+
2020-07-08,1160.83,1170.17,1134.96,1137.31,1137.31,2997732
|
|
73
|
+
2020-07-09,1136.54,1139.19,1112.07,1119.0,1119.0,2087767
|
|
74
|
+
2020-07-10,1115.75,1129.2,1110.13,1115.76,1115.76,2968171
|
|
75
|
+
2020-07-13,1107.4,1109.65,1087.26,1096.27,1096.27,2667840
|
|
76
|
+
2020-07-14,1087.64,1102.08,1072.45,1074.97,1074.97,1330149
|
|
77
|
+
2020-07-15,1068.96,1098.45,1064.98,1096.19,1096.19,1729409
|
|
78
|
+
2020-07-16,1088.48,1103.85,1080.43,1089.53,1089.53,2274763
|
|
79
|
+
2020-07-17,1082.89,1109.96,1071.17,1100.07,1100.07,1680385
|
|
80
|
+
2020-07-20,1093.35,1117.17,1083.83,1111.13,1111.13,2508443
|
|
81
|
+
2020-07-21,1119.29,1132.84,1105.05,1125.96,1125.96,2031855
|
|
82
|
+
2020-07-22,1129.77,1139.92,1105.63,1108.95,1108.95,2464929
|
|
83
|
+
2020-07-23,1110.96,1136.3,1096.17,1132.73,1132.73,1372256
|
|
84
|
+
2020-07-24,1131.3,1138.12,1116.82,1125.4,1125.4,2631227
|
|
85
|
+
2020-07-27,1123.8,1132.17,1091.86,1099.5,1099.5,2719126
|
|
86
|
+
2020-07-28,1106.07,1127.23,1098.41,1116.03,1116.03,3388364
|
|
87
|
+
2020-07-29,1111.43,1152.04,1102.43,1139.53,1139.53,3227935
|
|
88
|
+
2020-07-30,1146.04,1156.31,1139.85,1146.61,1146.61,2229681
|
|
89
|
+
2020-07-31,1138.34,1172.49,1133.17,1159.03,1159.03,3149128
|
|
90
|
+
2020-08-03,1162.39,1175.1,1153.96,1168.73,1168.73,2563208
|
|
91
|
+
2020-08-04,1162.97,1175.34,1141.55,1147.97,1147.97,2358754
|
|
92
|
+
2020-08-05,1148.3,1158.35,1143.16,1153.87,1153.87,2904683
|
|
93
|
+
2020-08-06,1159.03,1171.88,1148.63,1160.9,1160.9,3258653
|
|
94
|
+
2020-08-07,1151.24,1157.07,1143.63,1150.89,1150.89,2220495
|
|
95
|
+
2020-08-10,1152.52,1160.67,1135.46,1144.36,1144.36,2984692
|
|
96
|
+
2020-08-11,1145.37,1181.75,1137.47,1175.18,1175.18,2486070
|
|
97
|
+
2020-08-12,1167.59,1172.09,1152.87,1156.42,1156.42,3447576
|
|
98
|
+
2020-08-13,1160.22,1192.01,1148.62,1187.52,1187.52,2359723
|
|
99
|
+
2020-08-14,1197.05,1220.72,1191.37,1211.9,1211.9,1621637
|
|
100
|
+
2020-08-17,1207.82,1235.3,1201.89,1228.61,1228.61,3440324
|
|
101
|
+
2020-08-18,1219.52,1222.23,1195.68,1201.48,1201.48,1729654
|
|
102
|
+
2020-08-19,1206.54,1219.95,1204.38,1216.62,1216.62,2392605
|
|
103
|
+
2020-08-20,1215.43,1220.65,1212.76,1216.25,1216.25,3203741
|
|
104
|
+
2020-08-21,1207.56,1215.95,1179.33,1188.83,1188.83,1424852
|
|
105
|
+
2020-08-24,1195.05,1209.39,1175.28,1178.39,1178.39,2240988
|
|
106
|
+
2020-08-25,1183.68,1193.56,1152.91,1165.19,1165.19,2146600
|
|
107
|
+
2020-08-26,1162.8,1194.27,1156.93,1180.46,1180.46,2998642
|
|
108
|
+
2020-08-27,1182.88,1192.81,1163.06,1174.68,1174.68,2071525
|
|
109
|
+
2020-08-28,1169.97,1182.43,1164.85,1179.37,1179.37,1514844
|
|
110
|
+
2020-08-31,1177.54,1188.5,1153.04,1161.15,1161.15,1336901
|
|
111
|
+
2020-09-01,1165.29,1176.43,1145.12,1153.02,1153.02,2179050
|
|
112
|
+
2020-09-02,1158.78,1194.73,1148.18,1184.6,1184.6,2029713
|
|
113
|
+
2020-09-03,1185.49,1195.91,1170.06,1183.87,1183.87,1796582
|
|
114
|
+
2020-09-04,1177.19,1183.19,1144.38,1156.12,1156.12,2410520
|
|
115
|
+
2020-09-07,1155.49,1161.44,1147.41,1154.64,1154.64,2341883
|
|
116
|
+
2020-09-08,1154.52,1160.1,1152.0,1157.05,1157.05,3012059
|
|
117
|
+
2020-09-09,1159.12,1176.86,1154.14,1174.52,1174.52,1287012
|
|
118
|
+
2020-09-10,1177.97,1213.45,1175.45,1207.95,1207.95,1934803
|
|
119
|
+
2020-09-11,1210.98,1225.77,1206.62,1211.86,1211.86,3028234
|
|
120
|
+
2020-09-14,1211.69,1224.79,1205.17,1221.6,1221.6,2597996
|
|
121
|
+
2020-09-15,1213.69,1217.78,1199.0,1206.35,1206.35,3278147
|
|
122
|
+
2020-09-16,1215.25,1227.83,1196.95,1206.1,1206.1,3107678
|
|
123
|
+
2020-09-17,1201.15,1204.66,1168.95,1180.99,1180.99,3358373
|
|
124
|
+
2020-09-18,1171.01,1204.68,1163.0,1191.38,1191.38,1427348
|
|
125
|
+
2020-09-21,1188.62,1200.45,1163.81,1173.94,1173.94,1416475
|
|
126
|
+
2020-09-22,1174.92,1188.98,1153.42,1161.12,1161.12,3233028
|
|
127
|
+
2020-09-23,1170.58,1180.5,1147.15,1152.26,1152.26,1864286
|
|
128
|
+
2020-09-24,1142.53,1149.83,1129.7,1134.62,1134.62,1675890
|
|
129
|
+
2020-09-25,1126.97,1140.17,1118.49,1127.35,1127.35,2424156
|
|
130
|
+
2020-09-28,1122.82,1138.66,1108.08,1125.81,1125.81,2222281
|
|
131
|
+
2020-09-29,1118.7,1123.3,1108.91,1118.82,1118.82,1772557
|
|
132
|
+
2020-09-30,1114.34,1149.13,1106.95,1136.86,1136.86,3329606
|
|
133
|
+
2020-10-01,1126.91,1138.35,1103.71,1116.6,1116.6,3253700
|
|
134
|
+
2020-10-02,1115.53,1146.42,1109.21,1138.12,1138.12,3479310
|
|
135
|
+
2020-10-05,1146.78,1160.08,1127.78,1142.53,1142.53,2201623
|
|
136
|
+
2020-10-06,1137.2,1155.73,1134.63,1143.65,1143.65,3183806
|
|
137
|
+
2020-10-07,1149.88,1170.69,1139.25,1163.67,1163.67,1837975
|
|
138
|
+
2020-10-08,1154.41,1165.18,1144.74,1156.65,1156.65,1620959
|
|
139
|
+
2020-10-09,1155.46,1187.38,1147.52,1178.54,1178.54,1804631
|
|
140
|
+
2020-10-12,1181.64,1185.65,1171.09,1179.19,1179.19,2311586
|
|
141
|
+
2020-10-13,1183.04,1193.49,1163.59,1176.66,1176.66,3438174
|
|
142
|
+
2020-10-14,1172.99,1184.33,1157.02,1168.89,1168.89,3469185
|
|
143
|
+
2020-10-15,1160.26,1170.47,1123.26,1137.23,1137.23,2154146
|