making-with-code-cli 4.1.1__tar.gz → 5.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.
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0}/PKG-INFO +14 -14
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0}/pyproject.toml +21 -16
- making_with_code_cli-5.0.0/src/making_with_code_cli/__init__.py +0 -0
- making_with_code_cli-5.0.0/src/making_with_code_cli/git_backend/base_backend.py +33 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/git_backend/mwc_backend.py +26 -1
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/settings.py +8 -5
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/setup/__init__.py +6 -3
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/setup/tasks.py +64 -100
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/check/check_module.py +2 -2
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/update/__init__.py +1 -0
- making_with_code_cli-4.1.1/making_with_code_cli/git_backend/base_backend.py +0 -47
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0}/README.md +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/cli.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/curriculum.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/decorators.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/errors.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/git_backend/__init__.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/git_wrapper.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/helpers.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/mwc_accounts_api.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/styles.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/submit.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/__init__.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/assess.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/check/__init__.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/gitea_api/api.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/gitea_api/exceptions.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/log.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/patch.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/section/__init__.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/section/create.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/section/edit.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/section/show.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/setup.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/status.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/student/__init__.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/student/create.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/student/update.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/student_repo_functions.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/student_repos.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/update.py +0 -0
- {making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/version.py +0 -0
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: making-with-code-cli
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.0
|
|
4
4
|
Summary: Courseware for Making With Code
|
|
5
|
-
License: MIT
|
|
6
5
|
Author: Chris Proctor
|
|
7
|
-
Author-email: chris@chrisproctor.net
|
|
8
|
-
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
6
|
+
Author-email: Chris Proctor <chris@chrisproctor.net>
|
|
7
|
+
License: MIT
|
|
10
8
|
Classifier: Programming Language :: Python :: 3
|
|
11
9
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
-
|
|
15
|
-
Requires-Dist:
|
|
16
|
-
Requires-Dist:
|
|
17
|
-
Requires-Dist:
|
|
18
|
-
Requires-Dist:
|
|
19
|
-
Requires-Dist:
|
|
20
|
-
Requires-Dist:
|
|
21
|
-
Requires-Dist: tqdm
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Requires-Dist: pyyaml>=6.0.2,<7.0.0
|
|
14
|
+
Requires-Dist: click>=8.1.8,<9.0.0
|
|
15
|
+
Requires-Dist: requests>=2.32.3,<3.0.0
|
|
16
|
+
Requires-Dist: tabulate>=0.9.0,<0.10.0
|
|
17
|
+
Requires-Dist: gitpython>=3.1.44,<4.0.0
|
|
18
|
+
Requires-Dist: dateparser>=1.2.0,<2.0.0
|
|
19
|
+
Requires-Dist: tqdm>=4.67.1,<5.0.0
|
|
20
|
+
Requires-Dist: tomlkit>=0.14.0
|
|
21
|
+
Requires-Python: >=3.11, <4.0
|
|
22
|
+
Project-URL: documentation, https://docs.makingwithcode.org/making-with-code-cli
|
|
22
23
|
Project-URL: issues, https://github.com/cproctor/making-with-code-courseware/issues
|
|
23
24
|
Description-Content-Type: text/markdown
|
|
24
25
|
|
|
@@ -50,4 +51,3 @@ Once installed, you can set up your computer using the `mwc setup` command. Run
|
|
|
50
51
|
|
|
51
52
|
If you're interested in computing education and want to learn more about Making With Code,
|
|
52
53
|
please contact [Dr. Chris Proctor](https://chrisproctor.net).
|
|
53
|
-
|
|
@@ -1,38 +1,43 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "making-with-code-cli"
|
|
3
|
-
version = "
|
|
3
|
+
version = "5.0.0"
|
|
4
4
|
description = "Courseware for Making With Code"
|
|
5
|
-
authors = [
|
|
6
|
-
{name = "Chris Proctor",email = "chris@chrisproctor.net"}
|
|
7
|
-
]
|
|
8
|
-
license = {text = "MIT"}
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
homepage = "https://github.com/cproctor/making-with-code-courseware"
|
|
5
|
+
authors = [{ name = "Chris Proctor", email = "chris@chrisproctor.net" }]
|
|
11
6
|
requires-python = ">=3.11,<4.0"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
license = { text = "MIT" }
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Programming Language :: Python :: 3",
|
|
11
|
+
"Programming Language :: Python :: 3.11",
|
|
12
|
+
"Programming Language :: Python :: 3.12",
|
|
13
|
+
"Programming Language :: Python :: 3.13",
|
|
14
|
+
"Programming Language :: Python :: 3.14",
|
|
15
|
+
]
|
|
12
16
|
dependencies = [
|
|
13
17
|
"pyyaml (>=6.0.2,<7.0.0)",
|
|
14
18
|
"click (>=8.1.8,<9.0.0)",
|
|
15
19
|
"requests (>=2.32.3,<3.0.0)",
|
|
16
|
-
"toml (>=0.10.2,<0.11.0)",
|
|
17
20
|
"tabulate (>=0.9.0,<0.10.0)",
|
|
18
21
|
"gitpython (>=3.1.44,<4.0.0)",
|
|
19
22
|
"dateparser (>=1.2.0,<2.0.0)",
|
|
20
23
|
"tqdm (>=4.67.1,<5.0.0)",
|
|
24
|
+
"tomlkit>=0.14.0",
|
|
21
25
|
]
|
|
26
|
+
homepage = "https://github.com/cproctor/making-with-code-courseware"
|
|
22
27
|
|
|
23
28
|
[project.urls]
|
|
29
|
+
documentation = "https://docs.makingwithcode.org/making-with-code-cli"
|
|
24
30
|
issues = "https://github.com/cproctor/making-with-code-courseware/issues"
|
|
25
31
|
|
|
26
32
|
[project.scripts]
|
|
27
33
|
mwc = "making_with_code_cli.cli:cli"
|
|
28
34
|
|
|
29
35
|
[build-system]
|
|
30
|
-
requires = ["
|
|
31
|
-
build-backend = "
|
|
36
|
+
requires = ["uv_build>=0.9.0,<0.10.0"]
|
|
37
|
+
build-backend = "uv_build"
|
|
32
38
|
|
|
33
|
-
[
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
sphinx-rtd-theme = "^3.0.2"
|
|
39
|
+
[dependency-groups]
|
|
40
|
+
docs = [
|
|
41
|
+
"sphinx>=8.2.3,<9",
|
|
42
|
+
"sphinx-rtd-theme>=3.0.2,<4",
|
|
43
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from subprocess import run, CalledProcessError
|
|
3
|
+
import click
|
|
4
|
+
from making_with_code_cli.helpers import cd
|
|
5
|
+
from making_with_code_cli.setup.tasks import WORK_DIR_PERMISSIONS
|
|
6
|
+
from making_with_code_cli.styles import (
|
|
7
|
+
address,
|
|
8
|
+
info,
|
|
9
|
+
confirm,
|
|
10
|
+
error,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
class GitBackend:
|
|
14
|
+
"""Base class interface to backend git server.
|
|
15
|
+
All Making With Code deployments are backed by a git server, but the nature of the
|
|
16
|
+
server and the strategies for completing tasks vary by backend.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, settings):
|
|
20
|
+
self.settings = settings
|
|
21
|
+
|
|
22
|
+
def init_module(self, module, modpath):
|
|
23
|
+
raise NotImplemented()
|
|
24
|
+
|
|
25
|
+
def update(self, module, modpath, install=True):
|
|
26
|
+
raise NotImplemented()
|
|
27
|
+
|
|
28
|
+
def work_dir(self):
|
|
29
|
+
return Path(self.settings['work_dir'])
|
|
30
|
+
|
|
31
|
+
def relative_path(self, path):
|
|
32
|
+
return path.relative_to(self.work_dir())
|
|
33
|
+
|
|
@@ -38,8 +38,33 @@ class MWCBackend(GitBackend):
|
|
|
38
38
|
with cd(modpath.parent):
|
|
39
39
|
self.clone_repo(repo_name)
|
|
40
40
|
if (modpath / self.COMMIT_TEMPLATE).exists():
|
|
41
|
+
run(f"git config commit.template {self.COMMIT_TEMPLATE}", shell=True,
|
|
42
|
+
check=True, cwd=modpath)
|
|
43
|
+
run("uv venv", shell=True, check=True, cwd=modpath)
|
|
44
|
+
self.init_direnv(modpath)
|
|
45
|
+
|
|
46
|
+
def update(self, module, modpath, install=True):
|
|
47
|
+
if (modpath / ".git").is_dir():
|
|
41
48
|
with cd(modpath):
|
|
42
|
-
|
|
49
|
+
relpath = self.relative_path(modpath)
|
|
50
|
+
try:
|
|
51
|
+
click.echo(address(f"Checking {relpath} for updates.", preformatted=True))
|
|
52
|
+
gitresult = run("git pull", shell=True, check=True, capture_output=True,
|
|
53
|
+
text=True)
|
|
54
|
+
click.echo(info(gitresult.stdout))
|
|
55
|
+
if install and Path("pyproject.toml").exists():
|
|
56
|
+
result = run("uv sync", shell=True, check=True,
|
|
57
|
+
capture_output=True, text=True)
|
|
58
|
+
self.init_direnv(modpath)
|
|
59
|
+
click.echo(info(result.stdout, preformatted=True))
|
|
60
|
+
except CalledProcessError as e:
|
|
61
|
+
click.echo(error(f"There was a problem updating {relpath}. Ask a teacher."))
|
|
62
|
+
raise e
|
|
63
|
+
|
|
64
|
+
def init_direnv(self, modpath):
|
|
65
|
+
if not (modpath / ".envrc").exists():
|
|
66
|
+
(modpath / ".envrc").write_text("source .venv/bin/activate")
|
|
67
|
+
run("direnv allow", shell=True, check=True, cwd=modpath)
|
|
43
68
|
|
|
44
69
|
def user_has_repo(self, repo_name, username=None):
|
|
45
70
|
"""Checks to see whether a user already has the named repo.
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/settings.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
import
|
|
2
|
+
import tomllib
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
5
|
|
|
@@ -14,7 +14,8 @@ def get_settings_path(settings_path=None):
|
|
|
14
14
|
elif "MWC_CONFIG" in os.environ:
|
|
15
15
|
return Path(os.environ["MWC_CONFIG"])
|
|
16
16
|
else:
|
|
17
|
-
|
|
17
|
+
xdg_config_home = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"))
|
|
18
|
+
return xdg_config_home / "settings.toml"
|
|
18
19
|
|
|
19
20
|
def read_settings(settings_path=None):
|
|
20
21
|
"""Reads the settings file and returns a dict.
|
|
@@ -22,7 +23,8 @@ def read_settings(settings_path=None):
|
|
|
22
23
|
"""
|
|
23
24
|
sp = get_settings_path(settings_path)
|
|
24
25
|
if sp.exists():
|
|
25
|
-
|
|
26
|
+
with open(sp, "rb") as f:
|
|
27
|
+
return tomllib.load(f)
|
|
26
28
|
else:
|
|
27
29
|
return {}
|
|
28
30
|
|
|
@@ -38,6 +40,7 @@ def iter_settings(settings, prefix=None):
|
|
|
38
40
|
else:
|
|
39
41
|
yield '.'.join(keypath), value
|
|
40
42
|
|
|
43
|
+
# TODO
|
|
41
44
|
def check_settings(settings):
|
|
42
45
|
"""Checks that all settings match SETTINGS_FORMAT"""
|
|
43
46
|
errors = []
|
|
@@ -45,5 +48,5 @@ def check_settings(settings):
|
|
|
45
48
|
def write_settings(settings, settings_path=None):
|
|
46
49
|
"""Writes the settings to the settings file."""
|
|
47
50
|
sp = get_settings_path(settings_path)
|
|
48
|
-
sp
|
|
49
|
-
|
|
51
|
+
with open(sp, "w") as f:
|
|
52
|
+
tomlkit.dump(settings, f)
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/setup/__init__.py
RENAMED
|
@@ -29,8 +29,10 @@ from making_with_code_cli.setup.tasks import (
|
|
|
29
29
|
choose_work_dir,
|
|
30
30
|
choose_course,
|
|
31
31
|
choose_editor,
|
|
32
|
+
WriteMWCShellConfig,
|
|
33
|
+
SourceMWCShellConfig,
|
|
32
34
|
InstallXCode,
|
|
33
|
-
|
|
35
|
+
InstallDirenv,
|
|
34
36
|
InstallGit,
|
|
35
37
|
InstallTree,
|
|
36
38
|
InstallVSCode,
|
|
@@ -99,14 +101,15 @@ def setup(ctx, config, debug, git_name, git_email, mwc_accounts_url):
|
|
|
99
101
|
write_settings(settings, config)
|
|
100
102
|
|
|
101
103
|
task_classes = [
|
|
104
|
+
WriteMWCShellConfig,
|
|
105
|
+
SourceMWCShellConfig,
|
|
102
106
|
InstallXCode,
|
|
103
|
-
|
|
107
|
+
InstallDirenv,
|
|
104
108
|
InstallGit,
|
|
105
109
|
InstallTree,
|
|
106
110
|
InstallVSCode,
|
|
107
111
|
InstallImageMagick,
|
|
108
112
|
InstallHttpie,
|
|
109
|
-
#InstallScipy,
|
|
110
113
|
GitConfiguration,
|
|
111
114
|
]
|
|
112
115
|
errors = []
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/setup/tasks.py
RENAMED
|
@@ -129,24 +129,6 @@ def choose_work_dir(default=None, teacher=False):
|
|
|
129
129
|
work_dir.mkdir(mode=WORK_DIR_PERMISSIONS, parents=True)
|
|
130
130
|
return work_dir
|
|
131
131
|
|
|
132
|
-
def choose_mwc_site_url(default=None):
|
|
133
|
-
"""Asks the user for the Making With Code site URL
|
|
134
|
-
"""
|
|
135
|
-
while True:
|
|
136
|
-
url = click.prompt(
|
|
137
|
-
question("What's the URL of your Making With Code website?"),
|
|
138
|
-
default=default,
|
|
139
|
-
)
|
|
140
|
-
if url.endswith('/'):
|
|
141
|
-
url = url[:-1]
|
|
142
|
-
try:
|
|
143
|
-
curriculum = get_curriculum({'mwc_site_url': url})
|
|
144
|
-
return url
|
|
145
|
-
except CurriculumSiteNotAvailable as err:
|
|
146
|
-
click.echo(error(str(err)))
|
|
147
|
-
except requests.exceptions.MissingSchema as e:
|
|
148
|
-
click.echo(error(str(e)))
|
|
149
|
-
|
|
150
132
|
def choose_course(options, default=None):
|
|
151
133
|
"""Asks the user which course they are part of"""
|
|
152
134
|
if len(options) == 0:
|
|
@@ -192,19 +174,28 @@ def get_shell_name():
|
|
|
192
174
|
return shellpath.stdout.split('/')[-1].strip()
|
|
193
175
|
|
|
194
176
|
def get_mwc_rc_path():
|
|
195
|
-
|
|
177
|
+
xdg_config_home = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"))
|
|
178
|
+
return xdg_config_home / "mwc" / "shell_config.sh"
|
|
196
179
|
|
|
197
180
|
def platform_rc_file():
|
|
198
181
|
shell = get_shell_name()
|
|
182
|
+
if shell == "zsh":
|
|
183
|
+
dothome = Path(os.environ.get("ZDOTDIR", Path.home()))
|
|
184
|
+
else:
|
|
185
|
+
dothome = Path.home()
|
|
199
186
|
candidates = [
|
|
200
|
-
("bash",
|
|
201
|
-
("bash",
|
|
202
|
-
("bash",
|
|
203
|
-
("
|
|
204
|
-
("zsh",
|
|
187
|
+
("bash", dothome / ".bashrc"),
|
|
188
|
+
("bash", dothome / ".bash_profile"),
|
|
189
|
+
("bash", dothome / ".bash_login"),
|
|
190
|
+
("bash", dothome / ".profile"),
|
|
191
|
+
("zsh", dothome / ".zshenv"),
|
|
192
|
+
("zsh", dothome / ".zshrc"),
|
|
193
|
+
("zsh", dothome / ".zprofile"),
|
|
194
|
+
("zsh", dothome / ".zlogin"),
|
|
205
195
|
]
|
|
206
196
|
for sh, rc in candidates:
|
|
207
197
|
if shell == sh and rc.exists():
|
|
198
|
+
click.echo(debug(f"Shell identified as {sh}. Using {rc} as rc file."))
|
|
208
199
|
return rc
|
|
209
200
|
raise IOError("Can't find an rc file.")
|
|
210
201
|
|
|
@@ -244,11 +235,43 @@ class SetupTask:
|
|
|
244
235
|
def executable_on_path(self, name):
|
|
245
236
|
return bool(run(f"which {name}", shell=True, capture_output=True).stdout)
|
|
246
237
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
238
|
+
class WriteMWCShellConfig(SetupTask):
|
|
239
|
+
description = "Write the MWC shell config file to ~/.config/mwc/shell_config.sh or XDG_CONFIG_HOME"
|
|
240
|
+
|
|
241
|
+
def is_complete(self):
|
|
242
|
+
p = get_mwc_rc_path()
|
|
243
|
+
return p.exists() and p.read_text() == self.generate_shell_config()
|
|
244
|
+
|
|
245
|
+
def run_task(self):
|
|
246
|
+
mwc_rc_path = get_mwc_rc_path()
|
|
247
|
+
config_text = self.generate_shell_config()
|
|
248
|
+
self.debug_log(f"Writing to {mwc_rc_path}:\n\n{config_text}\n\n")
|
|
249
|
+
mwc_rc_path.write_text(config_text)
|
|
250
|
+
|
|
251
|
+
def generate_shell_config(self):
|
|
252
|
+
"Generates the shell configuration file contents"
|
|
253
|
+
f = ""
|
|
254
|
+
shell = get_shell_name()
|
|
255
|
+
f += "# Making With Code RC File\n\n"
|
|
256
|
+
f += "## Hook direnv into shell\n"
|
|
257
|
+
f += f'eval "$(direnv hook {shell})"\n\n'
|
|
258
|
+
|
|
259
|
+
if Platform.detect() == Platform.MAC:
|
|
260
|
+
if self.settings['editor'] == "subl":
|
|
261
|
+
f += "## Add subl to $PATH\n"
|
|
262
|
+
subldir = "/Applications/Sublime Text.app/Contents/SharedSupport/bin"
|
|
263
|
+
f += f'export PATH="{subldir}:$PATH"\n\n'
|
|
264
|
+
shell = get_shell_name()
|
|
265
|
+
if shell == "zsh":
|
|
266
|
+
f += "## Initialize zsh autocomplete\n"
|
|
267
|
+
f += "fpath+=~/.zfunc\n"
|
|
268
|
+
f += "autoload -Uz compinit && compinit\n\n"
|
|
269
|
+
return f
|
|
270
|
+
|
|
271
|
+
class SourceMWCShellConfig(SetupTask):
|
|
272
|
+
"""Writes a line in the shell rc config file sourcing ~/.config/mwc/shell_config.sh.
|
|
250
273
|
"""
|
|
251
|
-
description = "
|
|
274
|
+
description = "Source MWC config file in the main shell config file"
|
|
252
275
|
|
|
253
276
|
def is_complete(self):
|
|
254
277
|
return f"source {get_mwc_rc_path()}" in platform_rc_file().read_text()
|
|
@@ -262,6 +285,7 @@ class MWCShellConfig(SetupTask):
|
|
|
262
285
|
fh.write(f"\n# MAKING WITH CODE\n")
|
|
263
286
|
fh.write(f'export PATH="$PATH:{mwcpath}"\n')
|
|
264
287
|
fh.write(f"source {get_mwc_rc_path()}\n")
|
|
288
|
+
click.echo(info(f"Updated your shell login file ({rc_file}). You may need to close and reopen Terminal."))
|
|
265
289
|
|
|
266
290
|
class InstallXCode(SetupTask):
|
|
267
291
|
description = "Install XCode"
|
|
@@ -278,78 +302,6 @@ class InstallXCode(SetupTask):
|
|
|
278
302
|
click.echo(address(msg))
|
|
279
303
|
run("xcode-select --install", shell=True, check=True)
|
|
280
304
|
|
|
281
|
-
class InstallPoetry(SetupTask):
|
|
282
|
-
description = "Install poetry"
|
|
283
|
-
|
|
284
|
-
def is_complete(self):
|
|
285
|
-
if self.executable_on_path("poetry"):
|
|
286
|
-
self.check_for_poetry2()
|
|
287
|
-
return True
|
|
288
|
-
|
|
289
|
-
def run_task(self):
|
|
290
|
-
click.echo(address("Installing poetry..."))
|
|
291
|
-
run("pipx install poetry", shell=True, check=True)
|
|
292
|
-
run("poetry self add poetry-plugin-shell", shell=True, check=True)
|
|
293
|
-
self.check_for_poetry2()
|
|
294
|
-
click.echo(address("Installing poetry tab completions..."))
|
|
295
|
-
shell = get_shell_name()
|
|
296
|
-
try:
|
|
297
|
-
if shell == "bash":
|
|
298
|
-
run("poetry completions bash > ~/.bash_completion", shell=True, check=True)
|
|
299
|
-
if shell == "zsh":
|
|
300
|
-
tab_completion_dir = Path("~/.zfunc")
|
|
301
|
-
tab_completion_dir.mkdir(exist_ok=True)
|
|
302
|
-
run("poetry completions zsh > ~/.zfunc/_poetry", shell=True, check=True)
|
|
303
|
-
except PermissionError:
|
|
304
|
-
click.echo(warn(f"Couldn't install tab completions for poetry. This is not a big deal."))
|
|
305
|
-
|
|
306
|
-
def check_for_poetry2(self, upgrade=True):
|
|
307
|
-
result = run("poetry --version", shell=True, check=True, capture_output=True, text=True)
|
|
308
|
-
match = re.search(r"(\d+)\.\d+\.\d+", result.stdout)
|
|
309
|
-
if match:
|
|
310
|
-
poetry_major_version = int(match.group(1))
|
|
311
|
-
if not poetry_major_version == 2:
|
|
312
|
-
if upgrade:
|
|
313
|
-
click.echo(info("Upgrading Poetry"))
|
|
314
|
-
run("pipx upgrade poetry", shell=True, check=True)
|
|
315
|
-
run("poetry self add poetry-plugin-shell", shell=True, check=True)
|
|
316
|
-
self.check_for_poetry2(upgrade=False)
|
|
317
|
-
else:
|
|
318
|
-
raise MWCInstallationError("Poetry 2 is required. Please upgrade.")
|
|
319
|
-
else:
|
|
320
|
-
raise MWCInstallationError("Could not determine Poetry version; Poetry 2 is required.")
|
|
321
|
-
|
|
322
|
-
class WriteShellConfig(SetupTask):
|
|
323
|
-
description = "Write the MWC shell configuration file ~/.mwc_rc"
|
|
324
|
-
|
|
325
|
-
def is_complete(self):
|
|
326
|
-
p = get_mwc_rc_path()
|
|
327
|
-
return p.exists() and p.read_text() == self.generate_shell_config()
|
|
328
|
-
|
|
329
|
-
def run_task(self):
|
|
330
|
-
click.echo(address("Writing the MWC shell configuration file..."))
|
|
331
|
-
mwc_rc_path = get_mwc_rc_path()
|
|
332
|
-
config_text = self.generate_shell_config()
|
|
333
|
-
self.debug_log(f"Writing to {mwc_rc_path}:\n\n{config_text}\n\n")
|
|
334
|
-
mwc_rc_path.write_text(config_text)
|
|
335
|
-
run(f"source {get_mwc_rc_path()}", shell=True, check=True)
|
|
336
|
-
|
|
337
|
-
def generate_shell_config(self):
|
|
338
|
-
"Generates the shell configuration file contents"
|
|
339
|
-
f = ""
|
|
340
|
-
shell = get_shell_name()
|
|
341
|
-
f += "# Making With Code RC File\n\n"
|
|
342
|
-
if Platform.detect() == Platform.MAC:
|
|
343
|
-
if self.settings['editor'] == "subl":
|
|
344
|
-
f += "## Add subl to $PATH\n"
|
|
345
|
-
subldir = "/Applications/Sublime Text.app/Contents/SharedSupport/bin"
|
|
346
|
-
f += f'export PATH="{subldir}:$PATH"\n\n'
|
|
347
|
-
shell = get_shell_name()
|
|
348
|
-
if shell == "zsh":
|
|
349
|
-
f += "fpath+=~/.zfunc\n"
|
|
350
|
-
f += "autoload -Uz compinit && compinit\n"
|
|
351
|
-
return f
|
|
352
|
-
|
|
353
305
|
class InstallPackage(SetupTask):
|
|
354
306
|
"""A subclass of SetupTask for packages to be installed by the Platform package manager.
|
|
355
307
|
"""
|
|
@@ -382,6 +334,18 @@ class InstallPackage(SetupTask):
|
|
|
382
334
|
self.debug_log(f"Running: {package_manager}{package_name}")
|
|
383
335
|
run(f"{package_manager}{package_name}", shell=True, check=True)
|
|
384
336
|
|
|
337
|
+
class InstallPackageFromInstaller(InstallPackage):
|
|
338
|
+
"""Install from a remotely-fetched installer specified as install_command.
|
|
339
|
+
"""
|
|
340
|
+
def run_task(self):
|
|
341
|
+
click.echo(address(f"Installing {self.executable_name}..."))
|
|
342
|
+
self.debug_log(f"Running: {self.install_command}")
|
|
343
|
+
run(self.install_command, shell=True, check=True)
|
|
344
|
+
|
|
345
|
+
class InstallDirenv(InstallPackageFromInstaller):
|
|
346
|
+
executable_name = "direnv"
|
|
347
|
+
install_command = "curl -sfL https://direnv.net/install.sh | bash"
|
|
348
|
+
|
|
385
349
|
class InstallGit(InstallPackage):
|
|
386
350
|
platform = Platform.MAC | Platform.UBUNTU
|
|
387
351
|
executable_name = brew_name = apt_name = "git"
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from subprocess import run
|
|
9
9
|
import requests
|
|
10
|
-
import
|
|
10
|
+
import tomllib
|
|
11
11
|
from git import Repo, InvalidGitRepositoryError, GitCommandError
|
|
12
12
|
|
|
13
13
|
DEFAULT_BRANCH_NAME = "main"
|
|
@@ -82,7 +82,7 @@ class TestMWCModule:
|
|
|
82
82
|
if not md_file.exists():
|
|
83
83
|
self.errors.append(f"pyproject.toml missing")
|
|
84
84
|
return
|
|
85
|
-
md =
|
|
85
|
+
md = tomllib.load(md_file)
|
|
86
86
|
pyversion = md['project'].get('requires-python')
|
|
87
87
|
if not pyversion == PYTHON_VERSION:
|
|
88
88
|
self.errors.append(f"python version is {pyversion}, expected {PYTHON_VERSION}")
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
from subprocess import run, CalledProcessError
|
|
3
|
-
import click
|
|
4
|
-
from making_with_code_cli.helpers import cd
|
|
5
|
-
from making_with_code_cli.setup.tasks import WORK_DIR_PERMISSIONS
|
|
6
|
-
from making_with_code_cli.styles import (
|
|
7
|
-
address,
|
|
8
|
-
info,
|
|
9
|
-
confirm,
|
|
10
|
-
error,
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
class GitBackend:
|
|
14
|
-
"""Base class interface to backend git server.
|
|
15
|
-
All Making With Code deployments are backed by a git server, but the nature of the
|
|
16
|
-
server and the strategies for completing tasks vary by backend.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
def __init__(self, settings):
|
|
20
|
-
self.settings = settings
|
|
21
|
-
|
|
22
|
-
def init_module(self, module, modpath):
|
|
23
|
-
raise NotImplemented()
|
|
24
|
-
|
|
25
|
-
def update(self, module, modpath, install=True):
|
|
26
|
-
if (modpath / ".git").is_dir():
|
|
27
|
-
with cd(modpath):
|
|
28
|
-
relpath = self.relative_path(modpath)
|
|
29
|
-
try:
|
|
30
|
-
click.echo(address(f"Checking {relpath} for updates.", preformatted=True))
|
|
31
|
-
gitresult = run("git pull", shell=True, check=True, capture_output=True,
|
|
32
|
-
text=True)
|
|
33
|
-
click.echo(info(gitresult.stdout))
|
|
34
|
-
if install and Path("pyproject.toml").exists():
|
|
35
|
-
result = run("poetry install", shell=True, check=True,
|
|
36
|
-
capture_output=True, text=True)
|
|
37
|
-
click.echo(info(result.stdout, preformatted=True))
|
|
38
|
-
except CalledProcessError as e:
|
|
39
|
-
click.echo(error(f"There was a problem updating {relpath}. Ask a teacher."))
|
|
40
|
-
raise e
|
|
41
|
-
|
|
42
|
-
def work_dir(self):
|
|
43
|
-
return Path(self.settings['work_dir'])
|
|
44
|
-
|
|
45
|
-
def relative_path(self, path):
|
|
46
|
-
return path.relative_to(self.work_dir())
|
|
47
|
-
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/curriculum.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/decorators.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/git_wrapper.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/styles.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/submit.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/__init__.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/assess.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/log.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/patch.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/setup.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/teach/update.py
RENAMED
|
File without changes
|
{making_with_code_cli-4.1.1 → making_with_code_cli-5.0.0/src}/making_with_code_cli/version.py
RENAMED
|
File without changes
|