mirror of
https://github.com/Code-For-Groningen/temmies.git
synced 2025-03-15 07:10:15 +01:00
Updated api to reflect new changes
This commit is contained in:
parent
3d9ba063ce
commit
82a072ee14
250
docs/api.md
250
docs/api.md
@ -17,8 +17,8 @@ On the first run, you will be prompted for your password. Then, on the next run(
|
||||
#### `login()`
|
||||
Logs in to Themis. Runs automatically when the class is initialized.
|
||||
|
||||
#### `get_year(start, end)`
|
||||
Returns an instance of a [`Year`](#year) (academic year) between `start` and `end`.
|
||||
#### `get_year(year_path)`
|
||||
Returns an instance of a [`Year`](#year) for the academic year specified by `year_path`.
|
||||
|
||||
```python
|
||||
year = themis.get_year(2023, 2024)
|
||||
@ -30,7 +30,7 @@ Returns a list of `Year` instances corresponding to all years visible to the use
|
||||
```python
|
||||
years = themis.all_years()
|
||||
```
|
||||
<sub> I don't see why you would need this, but it's here. </sub>
|
||||
|
||||
----
|
||||
|
||||
## `Year`
|
||||
@ -41,13 +41,20 @@ year = themis.get_year(2023, 2024)
|
||||
```
|
||||
|
||||
### Methods
|
||||
#### `get_course(name)`
|
||||
Returns an instance of a [`Course`](#course) with the name `name`.
|
||||
#### `get_course(course_title)`
|
||||
Returns an instance of a [`Course`](#course) with the title `course_title`.
|
||||
|
||||
```python
|
||||
pf = year.get_course("Programming Fundamentals (for CS)")
|
||||
```
|
||||
|
||||
#### `get_course_by_tag(course_tag)`
|
||||
Returns an instance of a [`Course`](#course) using the course identifier `course_tag`.
|
||||
|
||||
```python
|
||||
ai_course = year.get_course_by_tag("adinc-ai")
|
||||
```
|
||||
|
||||
#### `all_courses()`
|
||||
Returns a list of `Course` instances corresponding to all courses visible to the user in a given `Year`.
|
||||
|
||||
@ -66,160 +73,96 @@ assignments = pf.get_groups()
|
||||
|
||||
### Methods
|
||||
#### `get_groups(full=False)`
|
||||
Returns a list of `ExerciseGroup` instances corresponding to all exercise groups visible to the user in a given `Course`. The default argument is `full=False`, which will only return the top-level (name, link) of each exercise and folder in the group. If `full=True`, it will traverse the whole course.
|
||||
|
||||
You can traverse the course in both cases, although in different ways.
|
||||
|
||||
When you have fully traversed the course, you can access everything via indices and the `exercises` and `folders` attributes of the `ExerciseGroup` instances:
|
||||
Returns a list of `ExerciseGroup` or `Group` instances corresponding to all items visible to the user in a given `Course`. The default argument is `full=False`, which will only return the top-level (name, link) of each item. If `full=True`, it will traverse the whole course.
|
||||
|
||||
```python
|
||||
ai_group = ai_course.get_groups(full=True)
|
||||
exercise = ai_group[7].exercises[1] # Week 11 -> Suitcase packing
|
||||
exercise.submit(["suitcase.py"], silent=False)
|
||||
```
|
||||
|
||||
This is equivalent to the case in which we don't traverse the whole course using `get_group` like so:
|
||||
|
||||
```python
|
||||
ai_group = ai_course.get_group("Week 11")
|
||||
exercise = ai_group.get_group("Suitcase packing")
|
||||
exercise.submit(["suitcase.py"], silent=False)
|
||||
ai_groups = ai_course.get_groups(full=True)
|
||||
exercise = ai_groups[7].exercises[1]
|
||||
exercise.submit(["solution.py"], silent=False)
|
||||
```
|
||||
|
||||
#### `get_group(name, full=False)`
|
||||
Returns an instance of an `ExerciseGroup` with the name `name`. The default argument is `full=False`, which will only return the (name, link) of each exercise and folder in the group. If `full=True`, it will traverse the whole group.
|
||||
Returns an instance of an `ExerciseGroup` or `Group` with the name `name`. The default argument is `full=False`, which will only return the (name, link) of the group. If `full=True`, it will traverse the whole group.
|
||||
|
||||
```python
|
||||
week1 = pf.get_group("Week 1")
|
||||
```
|
||||
|
||||
#### `create_group(item_data)`
|
||||
Creates and returns a `Group` or `ExerciseGroup` instance based on `item_data`.
|
||||
|
||||
```python
|
||||
group = course.create_group(item_data)
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## `Group`
|
||||
|
||||
Represents an item in Themis, which can be either a folder (non-submittable) or an assignment (submittable).
|
||||
|
||||
### Methods
|
||||
#### `get_items()`
|
||||
Returns all items (groups and assignments) under this group.
|
||||
|
||||
```python
|
||||
items = week1.get_items()
|
||||
```
|
||||
|
||||
#### `get_item_by_title(title)`
|
||||
Returns a single item by its title (case-insensitive).
|
||||
|
||||
```python
|
||||
item = week1.get_item_by_title("Exercise 2")
|
||||
```
|
||||
|
||||
#### `get_status(text=False)`
|
||||
Retrieves the status of the group. When `text=True`, returns the status as strings. Otherwise, returns submission objects or strings.
|
||||
|
||||
```python
|
||||
status = group.get_status()
|
||||
leading_submission = status["leading"]
|
||||
```
|
||||
|
||||
#### `download_files(path=".")`
|
||||
Downloads all files available for this group to a directory `path`. Defaults to the current directory.
|
||||
|
||||
```python
|
||||
group.download_files()
|
||||
```
|
||||
|
||||
#### `download_tcs(path=".")`
|
||||
Downloads all test cases for this group to a directory `path`. Defaults to the current directory.
|
||||
|
||||
```python
|
||||
group.download_tcs()
|
||||
```
|
||||
|
||||
#### `submit(files, judge=True, wait=True, silent=True)`
|
||||
Submits the files to the group. Default arguments are `judge=True`, `wait=True`, and `silent=True`.
|
||||
|
||||
```python
|
||||
group.submit(["solution.py"], silent=False)
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## `ExerciseGroup`
|
||||
Setting the `full` flag to `True` will traverse the whole group.
|
||||
Represents a submittable exercise. Inherits from `Group`.
|
||||
|
||||
- Both folders and exercises are represented as `ExerciseGroup` instances.
|
||||
- Folders will have the `am_exercise` attribute set to `False`.
|
||||
- Folders can have the `download_files` method called on them.
|
||||
- Exercises can have the `submit`, `download_files`, and `download_tcs` methods called on them.
|
||||
|
||||
### Example of folder traversal
|
||||
Let's say we have a folder structure like this:
|
||||
```
|
||||
- Course Name
|
||||
- Week 1
|
||||
- Exercise 1
|
||||
- Exercise 2
|
||||
- Part 1
|
||||
- Part 2
|
||||
- Week 2
|
||||
- Exercise 1
|
||||
- Exercise 2
|
||||
```
|
||||
And we want to get to `Part 2` of `Week 1`'s `Exercise 2`. We would do this:
|
||||
### Additional Methods
|
||||
#### `submit(files)`
|
||||
Submits files to the exercise. Raises an error if the item is not submittable.
|
||||
|
||||
```python
|
||||
pf = year.get_course("Programming Fundamentals (for CS)")
|
||||
assignments = pf.get_groups()
|
||||
week1 = assignments[0] # Week 1
|
||||
exercise2 = week1.folders[1] # Exercise 2
|
||||
part2 = exercise2.exercises[1] # Part 2
|
||||
|
||||
# Or, if you don't want to traverse the whole course:
|
||||
week1 = pf.get_group("Week 1")
|
||||
exercise2 = week1.get_group("Exercise 2")
|
||||
part2 = exercise2.get_group("Part 2")
|
||||
```
|
||||
|
||||
### Methods
|
||||
#### `download_files(path=".")`
|
||||
Downloads all files in the exercise group to a directory `path`. Defaults to the current directory.
|
||||
|
||||
```python
|
||||
assignment.download_files()
|
||||
```
|
||||
|
||||
#### `download_tcs(path=".")`
|
||||
Downloads all test cases in the exercise group to a directory `path`. Defaults to the current directory.
|
||||
|
||||
```python
|
||||
assignment.download_tcs()
|
||||
```
|
||||
|
||||
#### `get_group(name, full=False)`
|
||||
This is used when you want to traverse the course dynamically (not recurse through the whole thing). You can use it even if you've traversed the whole course.
|
||||
|
||||
```python
|
||||
# Week 1 -> Exercise 2 -> Part 2
|
||||
week1 = pf.get_group("Week 1")
|
||||
exercise2 = week1.get_group("Exercise 2")
|
||||
part2 = exercise2.get_group("Part 2")
|
||||
|
||||
# This is equivalent to (but faster than):
|
||||
week1 = pf.get_groups(full=True)[0]
|
||||
exercise2 = week1.folders[1]
|
||||
part2 = exercise2.exercises[1]
|
||||
```
|
||||
|
||||
#### `submit(files, judge=True, wait=True, silent=True)`
|
||||
Submits the files to the exercise. The default arguments are `judge=True`, `wait=True`, and `silent=True`. Setting `judge=False` will not judge the submission immediately. Setting `wait=False` will not wait for the submission to finish. Turning off `silent` will print the submission status dynamically.
|
||||
|
||||
```python
|
||||
suitcase = ai_course.get_group("Week 11").get_group("Suitcase packing")
|
||||
suitcase.submit(["suitcase.py"], silent=False)
|
||||
|
||||
# Output:
|
||||
# Submitting to Suitcase packing
|
||||
# • suitcase.py
|
||||
# 1: ✅
|
||||
# 2: ✅
|
||||
# 3: ✅
|
||||
# ...
|
||||
```
|
||||
|
||||
#### `get_status(text=False)`
|
||||
Retrieves the status of the exercise group. When `text` is set to `True`, it will return the status as a dictionary of strings. Otherwise, it will return a dictionary where keys map to either strings or `Submission` objects. Common keys include `'leading'`, `'best'`, `'latest'`, etc.
|
||||
|
||||
```python
|
||||
pf = year.get_course("Programming Fundamentals (for CS)")
|
||||
exercise = pf.get_group("Lab Session 2").get_group("Recurrence")
|
||||
|
||||
# Get status
|
||||
status = exercise.get_status()
|
||||
print(status)
|
||||
|
||||
# Output:
|
||||
{
|
||||
'assignment': 'Recurrence',
|
||||
'group': 'Y.N. Here',
|
||||
'status': 'passed: Passed all test cases',
|
||||
'grade': '2.00',
|
||||
'total': '2',
|
||||
'output limit': '1',
|
||||
'passed': '1',
|
||||
'leading': <temmies.submission.Submission object at 0x...>,
|
||||
'best': <temmies.submission.Submission object at 0x...>,
|
||||
'latest': <temmies.submission.Submission object at 0x...>,
|
||||
'first_pass': <temmies.submission.Submission object at 0x...>,
|
||||
'last_pass': <temmies.submission.Submission object at 0x...>,
|
||||
'visible': 'Yes'
|
||||
}
|
||||
```
|
||||
|
||||
To access submission details:
|
||||
|
||||
```python
|
||||
leading_submission = status["leading"]
|
||||
print(leading_submission.get_files())
|
||||
exercise.submit(["solution.py"])
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## `Submission`
|
||||
### Usage
|
||||
```python
|
||||
submission = pf.get_group("Week 1").get_group("Exercise 1").get_group("Part 1").get_status()["leading"]
|
||||
```
|
||||
|
||||
Represents a submission for a specific exercise.
|
||||
|
||||
### Methods
|
||||
#### `get_test_cases()`
|
||||
@ -227,33 +170,13 @@ Returns a dictionary of test cases and their statuses.
|
||||
|
||||
```python
|
||||
test_cases = submission.get_test_cases()
|
||||
print(test_cases)
|
||||
|
||||
# Output:
|
||||
{'1': 'passed', '2': 'passed', '3': 'passed', '4': 'passed', '5': 'passed', '6': 'passed', '7': 'passed', '8': 'passed', '9': 'passed', '10': 'passed'}
|
||||
```
|
||||
|
||||
#### `get_info()`
|
||||
Returns a dictionary of information about the submission.
|
||||
Returns detailed information about the submission.
|
||||
|
||||
```python
|
||||
info = submission.get_info()
|
||||
print(info)
|
||||
|
||||
# Output:
|
||||
{
|
||||
'assignment': 'Part 1',
|
||||
'group': 'Y.N. Here',
|
||||
'uploaded_by': 'Y.N. Here s1234567',
|
||||
'created_on': 'Wed Sep 13 2023 12:51:37 GMT+0200',
|
||||
'submitted_on': 'Wed Sep 13 2023 12:51:37 GMT+0200',
|
||||
'status': 'passed: Passed all test cases',
|
||||
'files': [
|
||||
('recurrence.c', '/file/.../recurrence.c'),
|
||||
('compile.log', '/file/.../compile.log')
|
||||
],
|
||||
'language': 'c'
|
||||
}
|
||||
```
|
||||
|
||||
#### `get_files()`
|
||||
@ -261,13 +184,4 @@ Returns a list of uploaded files in the format `(name, URL)`.
|
||||
|
||||
```python
|
||||
files = submission.get_files()
|
||||
print(files)
|
||||
|
||||
# Output:
|
||||
[
|
||||
('recurrence.c', '/file/.../recurrence.c'),
|
||||
('compile.log', '/file/.../compile.log')
|
||||
]
|
||||
```
|
||||
|
||||
----
|
||||
|
@ -12,3 +12,10 @@
|
||||
- Prepended `get_` to all methods in `Submission`
|
||||
- Created base `Group` from which `Course` and `ExerciseGroup` inherit.
|
||||
- Using system keyring to store passwords (Issue #11)
|
||||
|
||||
### **Version 1.2.0**
|
||||
|
||||
#### **Codebase**
|
||||
- Moved all methods related to downloading files (including test cases) to `Group`.
|
||||
- Created `get_test_cases` and `get_files` methods in `Group`.
|
||||
- We are now using the [API](https://themis.housing.rug.nl/api/navigation/2023-2024) (which mysteriously appeared) to get the year/course structure.
|
@ -24,7 +24,7 @@ from temmies.themis import Themis
|
||||
themis = Themis("s-number") # You will be prompted for your password
|
||||
|
||||
# Get a year
|
||||
year = themis.get_year(2023, 2024)
|
||||
year = themis.get_year("2023-2024")
|
||||
|
||||
# Get a course
|
||||
course = year.get_course("Programming Fundamentals (for CS)")
|
||||
|
Loading…
x
Reference in New Issue
Block a user