Coverage for e2xgrader/exchange/fetch_assignment.py: 27%

48 statements  

« prev     ^ index     » next       coverage.py v7.4.2, created at 2024-03-14 13:22 +0100

1import glob 

2import os 

3from textwrap import dedent 

4 

5import nbformat 

6from nbgrader.exchange.default import ExchangeFetchAssignment 

7from nbgrader.utils import check_mode 

8 

9from ..preprocessors import PermuteTasks, Scramble 

10from .exchange import E2xExchange 

11 

12 

13class E2xExchangeFetchAssignment(E2xExchange, ExchangeFetchAssignment): 

14 def init_src(self): 

15 if self.coursedir.course_id == "": 

16 self.fail("No course id specified. Re-run with --course flag.") 

17 if not self.authenticator.has_access( 

18 self.coursedir.student_id, self.coursedir.course_id 

19 ): 

20 self.fail("You do not have access to this course.") 

21 

22 self.course_path = os.path.join(self.root, self.coursedir.course_id) 

23 self.outbound_path = os.path.join(self.course_path, self.outbound_directory) 

24 if self.personalized_outbound: 

25 self.src_path = os.path.join( 

26 self.outbound_path, 

27 os.getenv("JUPYTERHUB_USER"), 

28 self.coursedir.assignment_id, 

29 ) 

30 else: 

31 self.src_path = os.path.join( 

32 self.outbound_path, self.coursedir.assignment_id 

33 ) 

34 

35 if not os.path.isdir(self.src_path): 

36 self._assignment_not_found( 

37 self.src_path, os.path.join(self.outbound_path, "*") 

38 ) 

39 if not check_mode(self.src_path, read=True, execute=True): 

40 self.fail( 

41 "You don't have read permissions for the directory: {}".format( 

42 self.src_path 

43 ) 

44 ) 

45 

46 def do_scrambling(self, dest, student_id): 

47 self.log.info(f"Scrambling for {student_id}") 

48 scrambler = Scramble(seed=hash(student_id)) 

49 permuter = PermuteTasks(seed=hash(student_id)) 

50 for nb_path in glob.glob(os.path.join(dest, "*.ipynb")): 

51 nb = nbformat.read(nb_path, as_version=4) 

52 if len(nb.cells) > 0 and nb.cells[0].source.startswith("%% scramble"): 

53 resources = {} 

54 nb, resources = scrambler.preprocess(nb, resources) 

55 nb, resources = permuter.preprocess(nb, resources) 

56 nbformat.write(nb, nb_path) 

57 self.log.info("Scrambled") 

58 

59 def copy_files(self): 

60 self.log.info("Source: {}".format(self.src_path)) 

61 self.log.info("Destination: {}".format(self.dest_path)) 

62 self.do_copy(self.src_path, self.dest_path) 

63 self.do_scrambling(self.dest_path, os.getenv("JUPYTERHUB_USER")) 

64 self.log.info( 

65 "Fetched as: {} {}".format( 

66 self.coursedir.course_id, self.coursedir.assignment_id 

67 ) 

68 ) 

69 

70 def do_copy(self, src, dest): 

71 if self.personalized_outbound: 

72 personalized_src = os.path.join(src, os.getenv("JUPYTERHUB_USER")) 

73 if os.path.exists(personalized_src): 

74 src = personalized_src 

75 else: 

76 self.log.warning( 

77 dedent( 

78 f""" 

79 Using personalized outbound, but no directory for 

80 user {os.getenv('JUPYTERHUB_USER')} exists. 

81 """ 

82 ) 

83 ) 

84 super().do_copy(src, dest)