uw-course 1.0.1__tar.gz → 2.0.0__tar.gz

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.
Files changed (36) hide show
  1. uw_course-2.0.0/PKG-INFO +111 -0
  2. uw_course-2.0.0/README.md +80 -0
  3. uw_course-2.0.0/pyproject.toml +47 -0
  4. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/ClassSchedule/SearchInfo.py +2 -3
  5. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/ClassSchedule/__init__.py +0 -0
  6. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/ClassSchedule/runner.py +28 -17
  7. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/DB/__init__.py +0 -0
  8. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/DB/dbClass.py +20 -0
  9. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/Utiles/__init__.py +0 -0
  10. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/Utiles/manageDBClass.py +5 -0
  11. uw_course-2.0.0/uw_course/Utiles/randomColor.py +28 -0
  12. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course/__init__.py +0 -0
  13. uw_course-2.0.0/uw_course/main.py +16 -0
  14. uw_course-2.0.0/uw_course/pdfschedule.py +385 -0
  15. uw_course-2.0.0/uw_course/setting.py +10 -0
  16. uw_course-2.0.0/uw_course/ui/__init__.py +1 -0
  17. uw_course-2.0.0/uw_course/ui/app.py +730 -0
  18. uw_course-2.0.0/uw_course/ui/components.py +99 -0
  19. uw_course-2.0.0/uw_course/ui/constants.py +9 -0
  20. uw_course-2.0.0/uw_course/ui/schedule_view.py +87 -0
  21. uw_course-2.0.0/uw_course.egg-info/PKG-INFO +111 -0
  22. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course.egg-info/SOURCES.txt +7 -2
  23. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course.egg-info/requires.txt +4 -4
  24. uw_course-1.0.1/PKG-INFO +0 -95
  25. uw_course-1.0.1/README.md +0 -74
  26. uw_course-1.0.1/pyproject.toml +0 -36
  27. uw_course-1.0.1/uw_course/Utiles/colorMessage.py +0 -9
  28. uw_course-1.0.1/uw_course/Utiles/randomColor.py +0 -16
  29. uw_course-1.0.1/uw_course/main.py +0 -85
  30. uw_course-1.0.1/uw_course/setting.py +0 -5
  31. uw_course-1.0.1/uw_course.egg-info/PKG-INFO +0 -95
  32. {uw_course-1.0.1 → uw_course-2.0.0}/LICENSE +0 -0
  33. {uw_course-1.0.1 → uw_course-2.0.0}/setup.cfg +0 -0
  34. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course.egg-info/dependency_links.txt +0 -0
  35. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course.egg-info/entry_points.txt +0 -0
  36. {uw_course-1.0.1 → uw_course-2.0.0}/uw_course.egg-info/top_level.txt +0 -0
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.4
2
+ Name: uw-course
3
+ Version: 2.0.0
4
+ Summary: A course helper tool for managing UW courses schedule
5
+ Author-email: Jiucheng Zang <git.jiucheng@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/zangjiucheng/uw-course
8
+ Project-URL: Repository, https://github.com/zangjiucheng/uw-course
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Topic :: Education
17
+ Classifier: Topic :: Office/Business :: Scheduling
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: attrs
22
+ Requires-Dist: click
23
+ Requires-Dist: PyYAML
24
+ Requires-Dist: reportlab
25
+ Requires-Dist: certifi
26
+ Requires-Dist: dnspython
27
+ Requires-Dist: Pillow
28
+ Requires-Dist: pymongo
29
+ Requires-Dist: textual
30
+ Dynamic: license-file
31
+
32
+ # uw-course
33
+
34
+ [![PyPI version](https://badge.fury.io/py/uw-course.svg)](https://badge.fury.io/py/uw-course)
35
+
36
+
37
+ This is a project for UWaterloo students to help them get course information and generate a schedule for the next term.
38
+
39
+ MongoDB DashBoard: [LINK](https://charts.mongodb.com/charts-project-0-cbzai/public/dashboards/091bc68f-76df-48c0-aa69-b21af14c0a8a)
40
+
41
+ ### Example Schedule:
42
+
43
+ ![Image text](demo.png)
44
+
45
+ ---
46
+
47
+ ### Install Steps:
48
+ 1. Install Python3 (>= 3.10) [Python Website](https://www.python.org/downloads/)
49
+ 2. ```bash
50
+ pip install uw-course
51
+ ```
52
+
53
+ ---
54
+
55
+ ### Usage (TUI)
56
+
57
+ Run the terminal UI:
58
+ ```bash
59
+ uw-course
60
+ ```
61
+
62
+ You can:
63
+ - Check course details
64
+ - Build a schedule manually or load a plan file
65
+ - View the weekly schedule in the TUI
66
+ - Export the `.out` schedule to PDF
67
+
68
+ #### Schedule Plan File Format
69
+ 1. Create a new file named `schema.txt`
70
+ 2. Edit `schema.txt` with the following format:
71
+ ```txt
72
+ Class{year}{Winter/Spring/Fall}
73
+
74
+ {Course}{CourseName}, {ClassID}
75
+ {Course}{CourseName}, {ClassID}
76
+ ...
77
+ ```
78
+
79
+ Example:
80
+ ```txt
81
+ Class2025Winter
82
+
83
+ PHYS 234, 7166
84
+ CS 431, 8788
85
+ PMATH 351, 6382
86
+ CO 353, 6157
87
+ STAT 231, 6097
88
+ AMATH 250, 5967
89
+ ```
90
+ 3. Use the TUI to select “Load Plan” and provide the file path (default: `uw-course-files/schema.txt`).
91
+ 4. The program will generate `uw-course-files/schedule.out`, and you can export it to PDF from the TUI.
92
+
93
+ #### Output Location
94
+ All generated files are stored in `uw-course-files/`:
95
+ - `uw-course-files/schedule.out`
96
+ - `uw-course-files/schedule.pdf`
97
+ - `uw-course-files/schema.txt` (if saved from the TUI)
98
+
99
+ #### Any Idea or Question, welcome send me an email via: j7zang@uwaterloo.ca
100
+
101
+ ---
102
+
103
+ ## Credits
104
+
105
+ PDF export uses a modified version of `pdfschedule` by John Thorvald Wodder II. Thanks for the original project.
106
+
107
+ ---
108
+
109
+ ## License
110
+
111
+ This project is open-source and can be modified and used for personal or educational purposes. Attribution to the original creator is appreciated. (MIT License)
@@ -0,0 +1,80 @@
1
+ # uw-course
2
+
3
+ [![PyPI version](https://badge.fury.io/py/uw-course.svg)](https://badge.fury.io/py/uw-course)
4
+
5
+
6
+ This is a project for UWaterloo students to help them get course information and generate a schedule for the next term.
7
+
8
+ MongoDB DashBoard: [LINK](https://charts.mongodb.com/charts-project-0-cbzai/public/dashboards/091bc68f-76df-48c0-aa69-b21af14c0a8a)
9
+
10
+ ### Example Schedule:
11
+
12
+ ![Image text](demo.png)
13
+
14
+ ---
15
+
16
+ ### Install Steps:
17
+ 1. Install Python3 (>= 3.10) [Python Website](https://www.python.org/downloads/)
18
+ 2. ```bash
19
+ pip install uw-course
20
+ ```
21
+
22
+ ---
23
+
24
+ ### Usage (TUI)
25
+
26
+ Run the terminal UI:
27
+ ```bash
28
+ uw-course
29
+ ```
30
+
31
+ You can:
32
+ - Check course details
33
+ - Build a schedule manually or load a plan file
34
+ - View the weekly schedule in the TUI
35
+ - Export the `.out` schedule to PDF
36
+
37
+ #### Schedule Plan File Format
38
+ 1. Create a new file named `schema.txt`
39
+ 2. Edit `schema.txt` with the following format:
40
+ ```txt
41
+ Class{year}{Winter/Spring/Fall}
42
+
43
+ {Course}{CourseName}, {ClassID}
44
+ {Course}{CourseName}, {ClassID}
45
+ ...
46
+ ```
47
+
48
+ Example:
49
+ ```txt
50
+ Class2025Winter
51
+
52
+ PHYS 234, 7166
53
+ CS 431, 8788
54
+ PMATH 351, 6382
55
+ CO 353, 6157
56
+ STAT 231, 6097
57
+ AMATH 250, 5967
58
+ ```
59
+ 3. Use the TUI to select “Load Plan” and provide the file path (default: `uw-course-files/schema.txt`).
60
+ 4. The program will generate `uw-course-files/schedule.out`, and you can export it to PDF from the TUI.
61
+
62
+ #### Output Location
63
+ All generated files are stored in `uw-course-files/`:
64
+ - `uw-course-files/schedule.out`
65
+ - `uw-course-files/schedule.pdf`
66
+ - `uw-course-files/schema.txt` (if saved from the TUI)
67
+
68
+ #### Any Idea or Question, welcome send me an email via: j7zang@uwaterloo.ca
69
+
70
+ ---
71
+
72
+ ## Credits
73
+
74
+ PDF export uses a modified version of `pdfschedule` by John Thorvald Wodder II. Thanks for the original project.
75
+
76
+ ---
77
+
78
+ ## License
79
+
80
+ This project is open-source and can be modified and used for personal or educational purposes. Attribution to the original creator is appreciated. (MIT License)
@@ -0,0 +1,47 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "uw-course"
7
+ version = "2.0.0"
8
+ description = "A course helper tool for managing UW courses schedule"
9
+ authors = [
10
+ { name = "Jiucheng Zang", email = "git.jiucheng@gmail.com" }
11
+ ]
12
+ license = "MIT"
13
+ readme = "README.md"
14
+ requires-python = ">=3.10"
15
+ dependencies = [
16
+ "attrs",
17
+ "click",
18
+ "PyYAML",
19
+ "reportlab",
20
+ "certifi",
21
+ "dnspython",
22
+ "Pillow",
23
+ "pymongo",
24
+ "textual"
25
+ ]
26
+ classifiers = [
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Programming Language :: Python :: 3.12",
30
+ "Programming Language :: Python :: 3.13",
31
+ "Operating System :: MacOS",
32
+ "Operating System :: POSIX :: Linux",
33
+ "Operating System :: Microsoft :: Windows",
34
+ "Topic :: Education",
35
+ "Topic :: Office/Business :: Scheduling",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/zangjiucheng/uw-course"
40
+ Repository = "https://github.com/zangjiucheng/uw-course"
41
+
42
+ [project.scripts]
43
+ uw-course = "uw_course.main:main"
44
+
45
+ [tool.pypi]
46
+ repository = "https://pypi.org/project/uw-course"
47
+ github = "zangjiucheng/uw-course"
@@ -1,5 +1,4 @@
1
1
  import re
2
- from ..Utiles.colorMessage import *
3
2
 
4
3
 
5
4
  class Course():
@@ -20,7 +19,7 @@ class Course():
20
19
  self.courseIndex = course['ClassIndex']
21
20
  self.courseTitle = course['classTitle']
22
21
  self.courseSeat = course['availableSeat']
23
- if re.search("\d:\d*", self.time):
22
+ if re.search(r"\d:\d*", self.time):
24
23
  self.startTime = self.time[0:5]
25
24
  self.endTime = self.time[6:11]
26
25
  StartTimeFlag = False
@@ -37,7 +36,7 @@ class Course():
37
36
  self.weekDay = "H" if self.time[11:15] == "Th" else self.time[11:15]
38
37
  self.writeSchedule()
39
38
  else:
40
- print(WARNING + "Z_Z For course %s in class %s, Time Data Error Z_Z" % (self.courseIndex, self.classNum)+ENDC)
39
+ print("Z_Z For course %s in class %s, Time Data Error Z_Z" % (self.courseIndex, self.classNum))
41
40
 
42
41
  def writeSchedule(self):
43
42
  self.fileOut.write(
@@ -1,38 +1,49 @@
1
- from .SearchInfo import Course
2
- from ..Utiles.randomColor import randomColor, randomGray
3
- from ..setting import Setting
4
- from ..Utiles.colorMessage import *
1
+ from uw_course.ClassSchedule.SearchInfo import Course
2
+ from uw_course.Utiles.randomColor import randomColor, randomGray
3
+ from uw_course.setting import Setting
5
4
 
6
5
  from os import remove
7
6
 
8
7
  setting = Setting()
9
8
 
10
9
 
11
- def SearchCourse(dbClassUW, courseIndex):
10
+ def get_course_detail(dbClassUW, courseIndex):
12
11
  CourseDescribe = dbClassUW.CourseDescribe
12
+ if not courseIndex or " " not in courseIndex:
13
+ return None
13
14
  faculty = courseIndex.split(" ")[0]
14
15
  courseNum = courseIndex.split(" ")[1]
15
16
  FacultyList = CourseDescribe.find({"faculty": faculty})
16
17
  for course in FacultyList:
17
- if course["courseIndex"] == courseNum:
18
- print("\n" + "$" * 50 + "\n\n")
19
- print("Description: ", end="")
20
- print(course["courseDescription"])
21
- print("\ncourseCredit: ", end="")
22
- print(course["courseCredit"])
23
- print("\n\n" + "$" * 50)
24
- break
18
+ if course.get("courseIndex") == courseNum:
19
+ return course
20
+ return None
21
+
22
+
23
+ def SearchCourse(dbClassUW, courseIndex):
24
+ course = get_course_detail(dbClassUW, courseIndex)
25
+ if not course:
26
+ print("@_@ Course %s Not Found @_@" % (courseIndex))
27
+ return
28
+ print("\n" + "$" * 50 + "\n\n")
29
+ print("Description: ", end="")
30
+ print(course.get("courseDescription"))
31
+ print("\ncourseCredit: ", end="")
32
+ print(course.get("courseCredit"))
33
+ print("\n\n" + "$" * 50)
25
34
  print("\n\n")
26
35
 
27
36
 
28
- def SearchAvalibleInTerm(dbClassUW, courseIndex, classNum=None):
37
+ def SearchAvalibleInTerm(dbClassUW, courseIndex, classNum=None, quiet=False):
29
38
  ClassSchedule = dbClassUW.ClassSchedule
30
39
  courseSelect = ClassSchedule.find({"ClassIndex": courseIndex})
31
40
  if courseSelect == None:
32
- print(FAIL + "@_@ Course %s Not Found in %s @_@" % (courseIndex, dbClassUW.ClassCollectionName) + ENDC)
41
+ if not quiet:
42
+ print("@_@ Course %s Not Found in %s @_@" % (courseIndex, dbClassUW.ClassCollectionName))
33
43
  return None
34
44
  else:
35
- print(OKGREEN + "!! Found Course %s in %s !!" % (courseIndex, dbClassUW.ClassCollectionName) + ENDC)
45
+ if not quiet:
46
+ print("!! Found Course %s in %s !!" % (courseIndex, dbClassUW.ClassCollectionName))
36
47
  if classNum != None:
37
48
  return [courseIndex, classNum]
38
49
  return [courseIndex]
@@ -41,7 +52,7 @@ def SearchAvalibleInTerm(dbClassUW, courseIndex, classNum=None):
41
52
  def makeSchedule(dbClassUW, courseWishList: list, gray: bool=False):
42
53
  classSchedule = dbClassUW.ClassSchedule
43
54
  if gray:
44
- print(OKGREEN + "!! Make Schedule with Gray Color !!" + ENDC)
55
+ print("!! Make Schedule with Gray Color !!")
45
56
  try:
46
57
  remove(setting.outDir)
47
58
  except:
@@ -23,3 +23,23 @@ class dbClass:
23
23
  self.ClassCollectionName = collectionName
24
24
  self.ClassDATABASE.selectCollection(self.ClassCollectionName)
25
25
  self.ClassSchedule = self.ClassDATABASE.mongo_collection
26
+
27
+ def listClassCollections(self):
28
+ collections = self.ClassDATABASE.listCollections()
29
+ term_order = {"Winter": 0, "Spring": 1, "Fall": 2}
30
+
31
+ def sort_key(name):
32
+ if not name.startswith("Class"):
33
+ return (9999, 99, name)
34
+ tail = name[len("Class") :]
35
+ year = tail[:4]
36
+ term = tail[4:]
37
+ try:
38
+ year_value = int(year)
39
+ except ValueError:
40
+ year_value = 9999
41
+ term_value = term_order.get(term, 99)
42
+ return (year_value, term_value, name)
43
+
44
+ class_names = [name for name in collections if name.startswith("Class")]
45
+ return sorted(class_names, key=sort_key, reverse=True)
@@ -16,5 +16,10 @@ class connectDB:
16
16
  def selectCollection(self, collection_name):
17
17
  self.mongo_collection = self.mongo_db[collection_name]
18
18
 
19
+ def listCollections(self):
20
+ if self.mongo_db is None:
21
+ return []
22
+ return self.mongo_db.list_collection_names()
23
+
19
24
  def closeDB(self):
20
25
  self.client.close()
@@ -0,0 +1,28 @@
1
+ from random import choice
2
+
3
+ _PALETTE = [
4
+ "#1F77B4", # blue
5
+ "#FF7F0E", # orange
6
+ "#2CA02C", # green
7
+ "#D62728", # red
8
+ "#9467BD", # purple
9
+ "#8C564B", # brown
10
+ "#E377C2", # pink
11
+ "#7F7F7F", # gray
12
+ "#BCBD22", # olive
13
+ "#17BECF", # cyan
14
+ "#4E79A7", # blue
15
+ "#F28E2B", # orange
16
+ "#59A14F", # green
17
+ "#E15759", # red
18
+ "#76B7B2", # teal
19
+ "#EDC948", # yellow
20
+ ]
21
+
22
+
23
+ def randomColor():
24
+ return choice(_PALETTE)
25
+
26
+
27
+ def randomGray():
28
+ return "#9E9E9E"
@@ -0,0 +1,16 @@
1
+ import os
2
+ import sys
3
+
4
+ if __package__ in (None, ""):
5
+ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
6
+ __package__ = "uw_course"
7
+
8
+ from uw_course.ui.app import run_app
9
+
10
+
11
+ def main():
12
+ run_app()
13
+
14
+
15
+ if __name__ == "__main__":
16
+ main()