making-with-code-cli 2.0.5__tar.gz → 2.1.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.
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/PKG-INFO +1 -1
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/__init__.py +2 -0
- making_with_code_cli-2.1.0/making_with_code_cli/teach/assess.py +30 -0
- making_with_code_cli-2.1.0/making_with_code_cli/teach/patch.py +91 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/pyproject.toml +1 -1
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/README.md +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/cli.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/curriculum.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/errors.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/git_backend/__init__.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/git_backend/base_backend.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/git_backend/mwc_backend.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/git_wrapper.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/helpers.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/mwc_accounts_api.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/settings.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/setup/__init__.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/setup/tasks.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/styles.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/submit.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/check.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/gitea_api/api.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/gitea_api/exceptions.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/log.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/setup.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/status.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/student_repo_functions.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/student_repos.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/test/__init__.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/test/test_module.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/update.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/update/__init__.py +0 -0
- {making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/version.py +0 -0
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/__init__.py
RENAMED
|
@@ -3,6 +3,7 @@ from making_with_code_cli.teach.setup import setup
|
|
|
3
3
|
from making_with_code_cli.teach.update import update
|
|
4
4
|
from making_with_code_cli.teach.status import status
|
|
5
5
|
from making_with_code_cli.teach.log import log
|
|
6
|
+
from making_with_code_cli.teach.patch import patch
|
|
6
7
|
from making_with_code_cli.teach.test import test
|
|
7
8
|
|
|
8
9
|
@click.group()
|
|
@@ -13,4 +14,5 @@ teach.add_command(setup)
|
|
|
13
14
|
teach.add_command(update)
|
|
14
15
|
teach.add_command(status)
|
|
15
16
|
teach.add_command(log)
|
|
17
|
+
teach.add_command(patch)
|
|
16
18
|
teach.add_command(test)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# teach/assess.py
|
|
2
|
+
# ---------------
|
|
3
|
+
# Implements `mwc teach assess`.
|
|
4
|
+
# This task iterates over student repos and assesses them.
|
|
5
|
+
#
|
|
6
|
+
# New settings:
|
|
7
|
+
# - I need some way of specifying a search root for assessment repos.
|
|
8
|
+
# Possibly teacher_assessment_repo_dir. We would search this directory
|
|
9
|
+
# for a directory having the same name as the lab being assessed. Within
|
|
10
|
+
# this direcory, we would locate assessment_policy.toml and possibly
|
|
11
|
+
# modules for testing. It would be recommended that assessment materials
|
|
12
|
+
# not be shared with students, but instead to be kept in an assessment
|
|
13
|
+
# branch of the base repos which are forked.
|
|
14
|
+
# Assessment:
|
|
15
|
+
# - A student module (lab, project, or problem set) is assessed according
|
|
16
|
+
# to a policy, which defines:
|
|
17
|
+
# - A front matter comment
|
|
18
|
+
# - The type of assessment (completion, points, or rubric)
|
|
19
|
+
# - The method of scoring:
|
|
20
|
+
# - Using a measure (e.g. number of commits, lines of code changed)
|
|
21
|
+
# - Using automated tests
|
|
22
|
+
# - Qualitatively through teacher interaction
|
|
23
|
+
# - Assessment is recorded in `assessment.md`, in a student's module repo.
|
|
24
|
+
# Machine-readable information is stored in TOML-based front matter, using
|
|
25
|
+
# an [[assessment]] table for each time assessment occurs. Each [[assessment]]
|
|
26
|
+
# has keys for date and score. The type of score depends on the type of assessment,
|
|
27
|
+
# and could be a string (effectively an enum) representing completion, a ratio
|
|
28
|
+
# (a two-integer array specifying points awarded and points possible), or
|
|
29
|
+
# a sub-table for rubric scores.
|
|
30
|
+
# - Assessment should be repeatable, with subsequent assessments appended to the record.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# teach/patch.py
|
|
2
|
+
# ---------------
|
|
3
|
+
# Implements `mwc teach patch`.
|
|
4
|
+
# This task patches a module for all students in a group.
|
|
5
|
+
# Patching is most useful when a change needs to be applied
|
|
6
|
+
# to a module after a course has started, and students each
|
|
7
|
+
# have their own copy of the repo.
|
|
8
|
+
|
|
9
|
+
import click
|
|
10
|
+
import git
|
|
11
|
+
from git import Repo
|
|
12
|
+
from making_with_code_cli.settings import read_settings
|
|
13
|
+
from making_with_code_cli.teach.setup import check_required_teacher_settings
|
|
14
|
+
from making_with_code_cli.teach.student_repos import StudentRepos
|
|
15
|
+
from making_with_code_cli.teach.update import update as update_task
|
|
16
|
+
from making_with_code_cli.styles import success, error
|
|
17
|
+
|
|
18
|
+
GIT_REMOTE_NAME = "origin"
|
|
19
|
+
|
|
20
|
+
@click.command()
|
|
21
|
+
@click.argument("patch")
|
|
22
|
+
@click.argument("group")
|
|
23
|
+
@click.argument("module")
|
|
24
|
+
@click.option("--config", help="Path to config file (default: ~/.mwc)")
|
|
25
|
+
@click.option('-c', "--course", help="Filter by course name")
|
|
26
|
+
@click.option('-u', "--user", help="Filter by username")
|
|
27
|
+
@click.option('-n', "--no-commit", is_flag=True, help="Commit and push changes")
|
|
28
|
+
@click.option('-m', "--message", default="Applying patch", help="Commit message")
|
|
29
|
+
@click.option('-t', "--threads", type=int, default=8, help="Maximum simultaneous threads")
|
|
30
|
+
def patch(patch, group, module, config, course, user, no_commit, message, threads):
|
|
31
|
+
settings = read_settings(config)
|
|
32
|
+
if not check_required_teacher_settings(settings):
|
|
33
|
+
return
|
|
34
|
+
update_task.callback(config, group, course, user, None, module, threads)
|
|
35
|
+
apply_patch = apply_patch_factory(patch, message, no_commit)
|
|
36
|
+
repos = StudentRepos(settings, threads)
|
|
37
|
+
results = repos.apply(apply_patch, group=group, course=course, module=module,
|
|
38
|
+
user=user, status_message=f"Applying patch {patch}")
|
|
39
|
+
for result in results:
|
|
40
|
+
if result['success']:
|
|
41
|
+
click.echo(success(f"SUCCESS: {result['path']}", preformatted=True))
|
|
42
|
+
else:
|
|
43
|
+
click.echo(error(f"ERROR: {result['path']}: {result['message']}", preformatted=True))
|
|
44
|
+
|
|
45
|
+
def apply_patch_factory(patch, commit_message, no_commit=False):
|
|
46
|
+
"""Creates a function which will apply a patch to a repo.
|
|
47
|
+
"""
|
|
48
|
+
def apply_patch(semaphore, results, group, username, path, token):
|
|
49
|
+
semaphore.acquire()
|
|
50
|
+
if path.exists():
|
|
51
|
+
repo = Repo(path)
|
|
52
|
+
if has_staged_changes(repo):
|
|
53
|
+
results.append({
|
|
54
|
+
"path": path,
|
|
55
|
+
"success": False,
|
|
56
|
+
"message": "Repo has staged changes."
|
|
57
|
+
})
|
|
58
|
+
elif has_unstaged_changes(repo):
|
|
59
|
+
results.append({
|
|
60
|
+
"path": path,
|
|
61
|
+
"success": False,
|
|
62
|
+
"message": "Repo has unstaged changes."
|
|
63
|
+
})
|
|
64
|
+
else:
|
|
65
|
+
try:
|
|
66
|
+
repo.git.apply(patch)
|
|
67
|
+
except git.exc.GitCommandError as e:
|
|
68
|
+
results.append({"path": path, "success": False, "message": str(e)})
|
|
69
|
+
return
|
|
70
|
+
if not no_commit:
|
|
71
|
+
try:
|
|
72
|
+
repo.git.add(update=True)
|
|
73
|
+
repo.index.commit(commit_message)
|
|
74
|
+
remote = repo.remote(name=GIT_REMOTE_NAME)
|
|
75
|
+
remote.push()
|
|
76
|
+
except Exception as e:
|
|
77
|
+
results.append({"path": path, "success": False, "message": str(e)})
|
|
78
|
+
return
|
|
79
|
+
results.append({"path": path, "success": True})
|
|
80
|
+
semaphore.release()
|
|
81
|
+
return apply_patch
|
|
82
|
+
|
|
83
|
+
def has_staged_changes(repo):
|
|
84
|
+
staged_changes = repo.index.diff("HEAD")
|
|
85
|
+
return len(staged_changes) > 0
|
|
86
|
+
|
|
87
|
+
def has_unstaged_changes(repo):
|
|
88
|
+
unstaged_changes = repo.index.diff(None)
|
|
89
|
+
return len(unstaged_changes) > 0
|
|
90
|
+
|
|
91
|
+
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/curriculum.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/git_wrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/mwc_accounts_api.py
RENAMED
|
File without changes
|
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/setup/__init__.py
RENAMED
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/setup/tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/check.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/setup.py
RENAMED
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/teach/update.py
RENAMED
|
File without changes
|
{making_with_code_cli-2.0.5 → making_with_code_cli-2.1.0}/making_with_code_cli/update/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|