making-with-code-cli 2.2.1__tar.gz → 3.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 (33) hide show
  1. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/PKG-INFO +6 -7
  2. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/errors.py +3 -0
  3. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/mwc_accounts_api.py +5 -1
  4. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/setup/tasks.py +23 -1
  5. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/check/__init__.py +5 -3
  6. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/check/check_module.py +15 -9
  7. making_with_code_cli-3.0.0/pyproject.toml +38 -0
  8. making_with_code_cli-2.2.1/pyproject.toml +0 -42
  9. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/README.md +0 -0
  10. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/cli.py +0 -0
  11. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/curriculum.py +0 -0
  12. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/git_backend/__init__.py +0 -0
  13. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/git_backend/base_backend.py +0 -0
  14. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/git_backend/mwc_backend.py +0 -0
  15. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/git_wrapper.py +0 -0
  16. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/helpers.py +0 -0
  17. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/settings.py +0 -0
  18. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/setup/__init__.py +0 -0
  19. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/styles.py +0 -0
  20. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/submit.py +0 -0
  21. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/__init__.py +0 -0
  22. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/assess.py +0 -0
  23. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/gitea_api/api.py +0 -0
  24. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/gitea_api/exceptions.py +0 -0
  25. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/log.py +0 -0
  26. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/patch.py +0 -0
  27. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/setup.py +0 -0
  28. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/status.py +0 -0
  29. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/student_repo_functions.py +0 -0
  30. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/student_repos.py +0 -0
  31. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/teach/update.py +0 -0
  32. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/update/__init__.py +0 -0
  33. {making_with_code_cli-2.2.1 → making_with_code_cli-3.0.0}/making_with_code_cli/version.py +0 -0
@@ -1,8 +1,7 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: making-with-code-cli
3
- Version: 2.2.1
3
+ Version: 3.0.0
4
4
  Summary: Courseware for Making With Code
5
- Home-page: https://github.com/cproctor/making-with-code-courseware
6
5
  License: MIT
7
6
  Author: Chris Proctor
8
7
  Author-email: chris@chrisproctor.net
@@ -13,11 +12,11 @@ Classifier: Programming Language :: Python :: 3.10
13
12
  Classifier: Programming Language :: Python :: 3.11
14
13
  Classifier: Programming Language :: Python :: 3.12
15
14
  Classifier: Programming Language :: Python :: 3.13
16
- Requires-Dist: PyYAML (>=6.0,<7.0)
17
- Requires-Dist: click (>=8.0.3,<9.0.0)
18
- Requires-Dist: dateparser (>=1.1.8,<2.0.0)
19
- Requires-Dist: gitpython (>=3.1.32,<4.0.0)
20
- Requires-Dist: requests (>=2.27.1,<3.0.0)
15
+ Requires-Dist: click (>=8.1.8,<9.0.0)
16
+ Requires-Dist: dateparser (>=1.2.0,<2.0.0)
17
+ Requires-Dist: gitpython (>=3.1.44,<4.0.0)
18
+ Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
19
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
21
20
  Requires-Dist: tabulate (>=0.9.0,<0.10.0)
22
21
  Requires-Dist: toml (>=0.10.2,<0.11.0)
23
22
  Requires-Dist: tqdm (>=4.67.1,<5.0.0)
@@ -21,5 +21,8 @@ class MissingSetting(MWCError):
21
21
  msg = f"Required setting {missing_setting} is missing. Please run mwc setup."
22
22
  super().__init__(msg)
23
23
 
24
+ class SoftwareInstallationError(MWCError):
25
+ pass
26
+
24
27
  class NoCurriculaAvailable(MWCError):
25
28
  pass
@@ -43,7 +43,11 @@ class MWCAccountsAPI:
43
43
  elif response.status_code == 500:
44
44
  raise self.ServerError("Error 500")
45
45
  else:
46
- raise self.RequestFailed(response.json())
46
+ try:
47
+ rj = response.json()
48
+ raise self.RequestFailed(rj)
49
+ except requests.exceptions.JSONDecodeError:
50
+ raise self.RequestFailed(response)
47
51
 
48
52
  class RequestFailed(Exception):
49
53
  pass
@@ -3,6 +3,7 @@ from enum import Flag, auto
3
3
  from stat import *
4
4
  import sys
5
5
  import os
6
+ import re
6
7
  import platform
7
8
  from importlib.util import find_spec
8
9
  from making_with_code_cli.mwc_accounts_api import MWCAccountsAPI
@@ -22,6 +23,7 @@ from making_with_code_cli.curriculum import (
22
23
  from making_with_code_cli.errors import (
23
24
  CurriculumSiteNotAvailable,
24
25
  NoCurriculaAvailable,
26
+ SoftwareInstallationError,
25
27
  )
26
28
  import click
27
29
  import requests
@@ -283,11 +285,15 @@ class InstallPoetry(SetupTask):
283
285
  description = "Install poetry"
284
286
 
285
287
  def is_complete(self):
286
- return self.executable_on_path("poetry")
288
+ if self.executable_on_path("poetry"):
289
+ self.check_for_poetry2()
290
+ return True
287
291
 
288
292
  def run_task(self):
289
293
  click.echo(address("Installing poetry..."))
290
294
  run("pipx install poetry", shell=True, check=True)
295
+ run("poetry self add poetry-plugin-shell", shell=True, check=True)
296
+ self.check_for_poetry2()
291
297
  click.echo(address("Installing poetry tab completions..."))
292
298
  shell = get_shell_name()
293
299
  try:
@@ -300,6 +306,22 @@ class InstallPoetry(SetupTask):
300
306
  except PermissionError:
301
307
  click.echo(warn(f"Couldn't install tab completions for poetry. This is not a big deal."))
302
308
 
309
+ def check_for_poetry2(self, upgrade=True):
310
+ result = run("poetry --version", shell=True, check=True, capture_output=True, text=True)
311
+ match = re.search(r"(\d+)\.\d+\.\d+", result.stdout)
312
+ if match:
313
+ poetry_major_version = int(match.group(1))
314
+ if not poetry_major_version == 2:
315
+ if upgrade:
316
+ click.echo(info("Upgrading Poetry"))
317
+ run("pipx upgrade poetry", shell=True, check=True)
318
+ run("poetry self add poetry-plugin-shell", shell=True, check=True)
319
+ self.check_for_poetry2(upgrade=False)
320
+ else:
321
+ raise MWCInstallationError("Poetry 2 is required. Please upgrade.")
322
+ else:
323
+ raise MWCInstallationError("Could not determine Poetry version; Poetry 2 is required.")
324
+
303
325
  class WriteShellConfig(SetupTask):
304
326
  description = "Write the MWC shell configuration file ~/.mwc_rc"
305
327
 
@@ -1,10 +1,10 @@
1
- from textwrap import fill
2
1
  import click
3
2
  import requests
4
3
  from pathlib import Path
5
4
  from tqdm import tqdm
6
5
  from making_with_code_cli.curriculum import get_curriculum
7
6
  from making_with_code_cli.teach.check.check_module import TestMWCModule
7
+ from making_with_code_cli.styles import info, warn
8
8
 
9
9
  @click.command()
10
10
  @click.argument("url")
@@ -35,10 +35,12 @@ def check(url, repo_dir, course, module, use_json):
35
35
  errors = test.run()
36
36
  if errors:
37
37
  results.append((slug, errors))
38
+ if len(test_cases) == 0:
39
+ print(warn("No matching modules."))
38
40
  if use_json:
39
41
  print([{'module': slug, 'errors': errors} for slug, errors in results])
40
42
  else:
41
43
  for slug, errors in results:
42
- print(slug)
44
+ print(info(slug))
43
45
  for error in errors:
44
- print(fill(error, width=80, initial_indent="- ", subsequent_indent=" "))
46
+ print(warn(error, list_format=True))
@@ -1,6 +1,8 @@
1
1
  # test_module.py
2
2
  # --------------
3
3
  # Defines a test case for a MWC module.
4
+ # TODO:
5
+ # - check minimum version 1.0
4
6
 
5
7
  from pathlib import Path
6
8
  from subprocess import run
@@ -9,7 +11,7 @@ import toml
9
11
  from git import Repo, InvalidGitRepositoryError, GitCommandError
10
12
 
11
13
  DEFAULT_BRANCH_NAME = "main"
12
- PYTHON_VERSION = ">=3.10"
14
+ PYTHON_VERSION = ">=3.10,<4.0"
13
15
 
14
16
  class TestCouldNotContinue(Exception):
15
17
  pass
@@ -26,8 +28,9 @@ class TestMWCModule:
26
28
  self.fetch_repo()
27
29
  self.test_curriculum_page_exists()
28
30
  self.test_has_commit_template()
29
- self.test_poetry()
30
- self.test_module_metadata()
31
+ poetry_ok = self.test_poetry()
32
+ if poetry_ok:
33
+ self.test_module_metadata()
31
34
  except TestCouldNotContinue as err:
32
35
  self.errors.append(str(err))
33
36
  return self.errors
@@ -45,7 +48,7 @@ class TestMWCModule:
45
48
  try:
46
49
  repo = Repo.clone_from(self.module_metadata['repo_url'], self.repo_path)
47
50
  except GitCommandError:
48
- raise TestCouldNotContinue("Could not clone repo")
51
+ raise TestCouldNotContinue(f"Could not clone repo ({self.module_metadata['repo_url']})")
49
52
  if not repo.active_branch.name == DEFAULT_BRANCH_NAME:
50
53
  self.errors.append(f"Default branch is not '{DEFAULT_BRANCH_NAME}'")
51
54
 
@@ -60,6 +63,11 @@ class TestMWCModule:
60
63
  if not ct.exists:
61
64
  self.errors.append(".commit_template is missing")
62
65
 
66
+ def test_has_gitignore(self):
67
+ gi = self.repo_path / ".gitignore"
68
+ if not gi.exists():
69
+ self.errors.append(".gitignore is missing")
70
+
63
71
  def test_poetry(self):
64
72
  result = run("poetry check", cwd=self.repo_path, shell=True, capture_output=True,
65
73
  text=True)
@@ -67,6 +75,7 @@ class TestMWCModule:
67
75
  for err in result.stderr.split('\n'):
68
76
  if err.strip():
69
77
  self.errors.append(err.strip())
78
+ return result.returncode == 0
70
79
 
71
80
  def test_module_metadata(self):
72
81
  md_file = self.repo_path/"pyproject.toml"
@@ -74,14 +83,11 @@ class TestMWCModule:
74
83
  self.errors.append(f"pyproject.toml missing")
75
84
  return
76
85
  md = toml.load(md_file)
77
- if not "project" in md:
78
- self.errors.append("'project' section missing from pyproject.toml")
79
- return
80
- if "tool" in md:
81
- self.errors.append("Deprecated 'tool' section found in pyproject.toml")
82
86
  pyversion = md['project'].get('requires-python')
83
87
  if not pyversion == PYTHON_VERSION:
84
88
  self.errors.append(f"python version is {pyversion}, expected {PYTHON_VERSION}")
89
+ if not md.get('tool', {}).get('poetry', {}).get('package-mode') == False:
90
+ self.errors.append("tool.poetry.package-mode must be false")
85
91
 
86
92
 
87
93
 
@@ -0,0 +1,38 @@
1
+ [project]
2
+ name = "making-with-code-cli"
3
+ version = "3.0.0"
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"
11
+ requires-python = ">=3.10,<4.0"
12
+ dependencies = [
13
+ "pyyaml (>=6.0.2,<7.0.0)",
14
+ "click (>=8.1.8,<9.0.0)",
15
+ "requests (>=2.32.3,<3.0.0)",
16
+ "toml (>=0.10.2,<0.11.0)",
17
+ "tabulate (>=0.9.0,<0.10.0)",
18
+ "gitpython (>=3.1.44,<4.0.0)",
19
+ "dateparser (>=1.2.0,<2.0.0)",
20
+ "tqdm (>=4.67.1,<5.0.0)"
21
+ ]
22
+
23
+ [project.urls]
24
+ issues = "https://github.com/cproctor/making-with-code-courseware/issues"
25
+
26
+ [project.scripts]
27
+ mwc = "making_with_code_cli.cli:cli"
28
+
29
+ [build-system]
30
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
31
+ build-backend = "poetry.core.masonry.api"
32
+
33
+ [tool.poetry.group.docs]
34
+ optional = true
35
+
36
+ [tool.poetry.group.docs.dependencies]
37
+ sphinx = "^7.3.7"
38
+ sphinx-rtd-theme = "^2.0.0"
@@ -1,42 +0,0 @@
1
- [tool.poetry]
2
- name = "making-with-code-cli"
3
- version = "2.2.1"
4
- description = "Courseware for Making With Code"
5
- authors = ["Chris Proctor <chris@chrisproctor.net>"]
6
- license = "MIT"
7
- readme = "README.md"
8
- homepage = "https://github.com/cproctor/making-with-code-courseware"
9
-
10
- [tool.poetry.dependencies]
11
- python = "^3.10"
12
- PyYAML = "^6.0"
13
- click = "^8.0.3"
14
- requests = "^2.27.1"
15
- toml = "^0.10.2"
16
- tabulate = "^0.9.0"
17
- gitpython = "^3.1.32"
18
- dateparser = "^1.1.8"
19
- tqdm = "^4.67.1"
20
-
21
- [tool.poetry.group.docs]
22
- optional = true
23
-
24
- [tool.poetry.group.docs.dependencies]
25
- sphinx = "^7.3.7"
26
- sphinx-rtd-theme = "^2.0.0"
27
-
28
- [tool.poetry.group.teacher]
29
- optional = true
30
-
31
- [tool.poetry.group.teacher.dependencies]
32
- gitpython = "^3.1.44"
33
-
34
- [build-system]
35
- requires = ["poetry-core>=1.0.0"]
36
- build-backend = "poetry.core.masonry.api"
37
-
38
- [tool.poetry.urls]
39
- issues = "https://github.com/cproctor/making-with-code-courseware/issues"
40
-
41
- [tool.poetry.scripts]
42
- mwc = "making_with_code_cli.cli:cli"