QuizGenerator 0.8.0__py3-none-any.whl → 0.9.0__py3-none-any.whl

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.
QuizGenerator/question.py CHANGED
@@ -15,10 +15,13 @@ import pprint
15
15
  import random
16
16
  import re
17
17
  import uuid
18
+ import types
19
+ import inspect
20
+ from types import MappingProxyType
18
21
 
19
22
  import pypandoc
20
23
  import yaml
21
- from typing import List, Dict, Any, Tuple, Optional
24
+ from typing import List, Dict, Any, Tuple, Optional, Mapping, MutableMapping
22
25
  import canvasapi.course, canvasapi.quiz
23
26
 
24
27
  import QuizGenerator.contentast as ca
@@ -58,6 +61,81 @@ class QuestionInstance:
58
61
  flags: RegenerationFlags
59
62
 
60
63
 
64
+ @dataclasses.dataclass
65
+ class QuestionContext:
66
+ rng_seed: Optional[int]
67
+ rng: random.Random
68
+ data: MutableMapping[str, Any] | Mapping[str, Any] = dataclasses.field(default_factory=dict)
69
+ frozen: bool = False
70
+ question_cls: type | None = None
71
+
72
+ def __getitem__(self, key: str) -> Any:
73
+ if key == "rng_seed":
74
+ return self.rng_seed
75
+ if key == "rng":
76
+ return self.rng
77
+ return self.data[key]
78
+
79
+ def __setitem__(self, key: str, value: Any) -> None:
80
+ if self.frozen:
81
+ raise TypeError("QuestionContext is frozen.")
82
+ if key == "rng_seed":
83
+ self.rng_seed = value
84
+ return
85
+ if key == "rng":
86
+ self.rng = value
87
+ return
88
+ if isinstance(self.data, MappingProxyType):
89
+ raise TypeError("QuestionContext is frozen.")
90
+ self.data[key] = value
91
+
92
+ def get(self, key: str, default: Any = None) -> Any:
93
+ if key == "rng_seed":
94
+ return self.rng_seed
95
+ if key == "rng":
96
+ return self.rng
97
+ return self.data.get(key, default)
98
+
99
+ def __contains__(self, key: object) -> bool:
100
+ if key in ("rng_seed", "rng"):
101
+ return True
102
+ return key in self.data
103
+
104
+ def __getattr__(self, name: str) -> Any:
105
+ if name in self.data:
106
+ return self.data[name]
107
+ if self.question_cls is not None and hasattr(self.question_cls, name):
108
+ raw_attr = inspect.getattr_static(self.question_cls, name)
109
+ if isinstance(raw_attr, staticmethod):
110
+ return raw_attr.__func__
111
+ if isinstance(raw_attr, classmethod):
112
+ return raw_attr.__func__.__get__(self.question_cls, self.question_cls)
113
+ attr = getattr(self.question_cls, name)
114
+ if callable(attr):
115
+ return types.MethodType(attr, self)
116
+ return attr
117
+ raise AttributeError(f"{type(self).__name__} has no attribute {name!r}")
118
+
119
+ def keys(self):
120
+ return self.data.keys()
121
+
122
+ def items(self):
123
+ return self.data.items()
124
+
125
+ def values(self):
126
+ return self.data.values()
127
+
128
+ def freeze(self) -> "QuestionContext":
129
+ frozen_data = MappingProxyType(dict(self.data))
130
+ return QuestionContext(
131
+ rng_seed=self.rng_seed,
132
+ rng=self.rng,
133
+ data=frozen_data,
134
+ frozen=True,
135
+ question_cls=self.question_cls,
136
+ )
137
+
138
+
61
139
  # Spacing presets for questions
62
140
  SPACING_PRESETS = {
63
141
  "NONE": 0,
@@ -262,7 +340,7 @@ class RegenerableChoiceMixin:
262
340
  self.register_choice('scheduler_kind', self.Kind, scheduler_kind, kwargs)
263
341
  super().__init__(**kwargs)
264
342
 
265
- def _build_context(self, rng_seed=None, **kwargs):
343
+ def _build_context(cls, rng_seed=None, **kwargs):
266
344
  self.rng.seed(rng_seed)
267
345
  # Get the choice (randomly selected or from config_params)
268
346
  self.scheduler_algorithm = self.get_choice('scheduler_kind', self.Kind)
@@ -382,6 +460,7 @@ class RegenerableChoiceMixin:
382
460
  del choice_info['_temp_fixed_value']
383
461
 
384
462
  class Question(abc.ABC):
463
+ AUTO_ENTRY_WARNINGS = True
385
464
  """
386
465
  Base class for all quiz questions with cross-format rendering support.
387
466
 
@@ -438,6 +517,7 @@ class Question(abc.ABC):
438
517
 
439
518
  # Default version - subclasses should override this
440
519
  VERSION = "1.0"
520
+ FREEZE_CONTEXT = False
441
521
 
442
522
  class Topic(enum.Enum):
443
523
  # CST334 (Operating Systems) Topics
@@ -546,8 +626,10 @@ class Question(abc.ABC):
546
626
  """
547
627
  # Generate the question, retrying with incremented seeds until we get an interesting one
548
628
  base_seed = kwargs.get("rng_seed", None)
629
+ max_backoff_attempts = kwargs.get("max_backoff_attempts", None)
549
630
  build_kwargs = dict(kwargs)
550
631
  build_kwargs.pop("rng_seed", None)
632
+ build_kwargs.pop("max_backoff_attempts", None)
551
633
  # Include config params so build() implementations can access YAML-provided settings.
552
634
  build_kwargs = {**self.config_params, **build_kwargs}
553
635
 
@@ -561,6 +643,10 @@ class Question(abc.ABC):
561
643
  is_interesting = False
562
644
  ctx = None
563
645
  while not is_interesting:
646
+ if max_backoff_attempts is not None and backoff_counter >= max_backoff_attempts:
647
+ raise RuntimeError(
648
+ f"Exceeded max_backoff_attempts={max_backoff_attempts} for {self.__class__.__name__}"
649
+ )
564
650
  # Increment seed for each backoff attempt to maintain deterministic behavior
565
651
  current_seed = None if base_seed is None else base_seed + backoff_counter
566
652
  ctx = self._build_context(
@@ -573,7 +659,17 @@ class Question(abc.ABC):
573
659
  # Store the actual seed used and question metadata for QR code generation
574
660
  actual_seed = None if base_seed is None else base_seed + backoff_counter - 1
575
661
 
576
- components = self.build(rng_seed=current_seed, context=ctx, **build_kwargs)
662
+ # Keep instance rng in sync for any legacy usage.
663
+ if isinstance(ctx, QuestionContext):
664
+ self.rng = ctx.rng
665
+ elif isinstance(ctx, dict) and "rng" in ctx:
666
+ self.rng = ctx["rng"]
667
+
668
+ components = self.__class__.build(
669
+ rng_seed=current_seed,
670
+ context=ctx,
671
+ **build_kwargs
672
+ )
577
673
 
578
674
  # Collect answers from explicit lists and inline AST
579
675
  inline_body_answers = self._collect_answers_from_ast(components.body)
@@ -584,6 +680,10 @@ class Question(abc.ABC):
584
680
 
585
681
  can_be_numerical = self._can_be_numerical_from_answers(answers)
586
682
 
683
+ if self.AUTO_ENTRY_WARNINGS:
684
+ warnings = self._entry_warnings_from_answers(answers)
685
+ components.body = self._append_entry_warnings(components.body, warnings)
686
+
587
687
  config_params = dict(self.config_params)
588
688
  if isinstance(ctx, dict) and ctx.get("_config_params"):
589
689
  config_params.update(ctx.get("_config_params"))
@@ -614,19 +714,27 @@ class Question(abc.ABC):
614
714
  def post_instantiate(self, instance, **kwargs):
615
715
  pass
616
716
 
617
- def build(self, *, rng_seed=None, context=None, **kwargs) -> QuestionComponents:
717
+ @classmethod
718
+ def build(cls, *, rng_seed=None, context=None, **kwargs) -> QuestionComponents:
618
719
  """
619
720
  Build question content (body, answers, explanation) for a given seed.
620
721
 
621
722
  This should only generate content; metadata like points/spacing belong in instantiate().
622
723
  """
623
- cls = self.__class__
624
724
  if context is None:
625
- context = self._build_context(rng_seed=rng_seed, **kwargs)
725
+ context = cls._coerce_context(
726
+ cls._build_context(rng_seed=rng_seed, **kwargs),
727
+ rng_seed=rng_seed
728
+ )
729
+ else:
730
+ context = cls._coerce_context(context, rng_seed=rng_seed)
731
+
732
+ if cls.FREEZE_CONTEXT:
733
+ context = context.freeze()
626
734
 
627
735
  # Build body + explanation. Each may return just an Element or (Element, answers).
628
- body, body_answers = cls._normalize_build_output(self._build_body(context))
629
- explanation, explanation_answers = cls._normalize_build_output(self._build_explanation(context))
736
+ body, body_answers = cls._normalize_build_output(cls._build_body(context))
737
+ explanation, explanation_answers = cls._normalize_build_output(cls._build_explanation(context))
630
738
 
631
739
  # Collect inline answers from both body and explanation.
632
740
  inline_body_answers = cls._collect_answers_from_ast(body)
@@ -645,30 +753,48 @@ class Question(abc.ABC):
645
753
  explanation=explanation
646
754
  )
647
755
 
648
- def _build_context(self, *, rng_seed=None, **kwargs):
756
+ @classmethod
757
+ def _coerce_context(cls, context, *, rng_seed=None) -> QuestionContext:
758
+ if isinstance(context, QuestionContext):
759
+ return context
760
+ if isinstance(context, dict):
761
+ ctx_seed = context.get("rng_seed", rng_seed)
762
+ rng = context.get("rng") or random.Random(ctx_seed)
763
+ ctx = QuestionContext(rng_seed=ctx_seed, rng=rng)
764
+ for key, value in context.items():
765
+ if key in ("rng_seed", "rng"):
766
+ continue
767
+ ctx.data[key] = value
768
+ return ctx
769
+ raise TypeError(f"Unsupported context type: {type(context)}")
770
+
771
+
772
+ @classmethod
773
+ def _build_context(cls, *, rng_seed=None, **kwargs) -> QuestionContext:
649
774
  """
650
775
  Build the deterministic context for a question instance.
651
776
 
652
- Override to return a context dict and avoid persistent self.* state.
777
+ Override to return a QuestionContext and avoid persistent self.* state.
653
778
  """
654
779
  rng = random.Random(rng_seed)
655
- # Keep instance rng in sync for questions that still use self.rng.
656
- self.rng = rng
657
- return {
658
- "rng_seed": rng_seed,
659
- "rng": rng,
660
- }
780
+ return QuestionContext(
781
+ rng_seed=rng_seed,
782
+ rng=rng,
783
+ question_cls=cls,
784
+ )
661
785
 
662
786
  @classmethod
663
787
  def is_interesting_ctx(cls, context) -> bool:
664
788
  """Context-aware hook; defaults to existing is_interesting()."""
665
789
  return True
666
790
 
667
- def _build_body(self, context) -> ca.Element | Tuple[ca.Element, List[ca.Answer]]:
791
+ @classmethod
792
+ def _build_body(cls, context) -> ca.Element | Tuple[ca.Element, List[ca.Answer]]:
668
793
  """Context-aware body builder."""
669
794
  raise NotImplementedError("Questions must implement _build_body().")
670
795
 
671
- def _build_explanation(self, context) -> ca.Element | Tuple[ca.Element, List[ca.Answer]]:
796
+ @classmethod
797
+ def _build_explanation(cls, context) -> ca.Element | Tuple[ca.Element, List[ca.Answer]]:
672
798
  """Context-aware explanation builder."""
673
799
  raise NotImplementedError("Questions must implement _build_explanation().")
674
800
 
@@ -723,6 +849,38 @@ class Question(abc.ABC):
723
849
  merged.append(ans)
724
850
  return merged
725
851
 
852
+ @classmethod
853
+ def _entry_warnings_from_answers(cls, answers: List[ca.Answer]) -> List[str]:
854
+ warnings: List[str] = []
855
+ seen: set[str] = set()
856
+ for answer in answers:
857
+ warning = None
858
+ if hasattr(answer.__class__, "get_entry_warning"):
859
+ warning = answer.__class__.get_entry_warning()
860
+ if not warning:
861
+ continue
862
+ if isinstance(warning, str):
863
+ warning_list = [warning]
864
+ else:
865
+ warning_list = list(warning)
866
+ for item in warning_list:
867
+ if item and item not in seen:
868
+ warnings.append(item)
869
+ seen.add(item)
870
+ return warnings
871
+
872
+ @classmethod
873
+ def _append_entry_warnings(cls, body: ca.Element, warnings: List[str]) -> ca.Element:
874
+ if not warnings:
875
+ return body
876
+ notes_lines = ["**Notes for answer entry**", ""]
877
+ notes_lines.extend(f"- {warning}" for warning in warnings)
878
+ warning_elements = ca.OnlyHtml([ca.Text("\n".join(notes_lines))])
879
+ if isinstance(body, ca.Container):
880
+ body.add_element(warning_elements)
881
+ return body
882
+ return ca.Section([body, warning_elements])
883
+
726
884
  @classmethod
727
885
  def _can_be_numerical_from_answers(cls, answers: List[ca.Answer]) -> bool:
728
886
  return (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: QuizGenerator
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Generate randomized quiz questions for Canvas LMS and PDF exams
5
5
  Project-URL: Homepage, https://github.com/OtterDen-Lab/QuizGenerator
6
6
  Project-URL: Documentation, https://github.com/OtterDen-Lab/QuizGenerator/tree/main/documentation
@@ -150,26 +150,29 @@ All questions follow the same three‑method flow:
150
150
 
151
151
  ```python
152
152
  class MyQuestion(Question):
153
- def _build_context(self, *, rng_seed=None, **kwargs):
153
+ @classmethod
154
+ def _build_context(cls, *, rng_seed=None, **kwargs):
154
155
  context = super()._build_context(rng_seed=rng_seed, **kwargs)
155
- rng = context["rng"]
156
+ rng = context.rng
156
157
  context["value"] = rng.randint(1, 10)
157
158
  return context
158
159
 
159
- def _build_body(self, context):
160
+ @classmethod
161
+ def _build_body(cls, context):
160
162
  body = ca.Section()
161
163
  body.add_element(ca.Paragraph([f"Value: {context['value']}"]))
162
164
  body.add_element(ca.AnswerTypes.Int(context["value"], label="Value"))
163
165
  return body
164
166
 
165
- def _build_explanation(self, context):
167
+ @classmethod
168
+ def _build_explanation(cls, context):
166
169
  explanation = ca.Section()
167
170
  explanation.add_element(ca.Paragraph([f"Answer: {context['value']}"]))
168
171
  return explanation
169
172
  ```
170
173
 
171
174
  Notes:
172
- - Always use `context["rng"]` for deterministic randomness.
175
+ - Always use `context.rng` (or `context["rng"]`) for deterministic randomness.
173
176
  - Avoid `refresh()`; it is no longer part of the API.
174
177
 
175
178
  ## Built-in Question Types
@@ -1,13 +1,13 @@
1
1
  QuizGenerator/__init__.py,sha256=8EV-k90A3PNC8Cm2-ZquwNyVyvnwW1gs6u-nGictyhs,840
2
2
  QuizGenerator/__main__.py,sha256=Dd9w4R0Unm3RiXztvR4Y_g9-lkWp6FHg-4VN50JbKxU,151
3
3
  QuizGenerator/constants.py,sha256=AO-UWwsWPLb1k2JW6KP8rl9fxTcdT0rW-6XC6zfnDOs,4386
4
- QuizGenerator/contentast.py,sha256=6eqhgjAGrkFQUoEOnnEuGIyllGnNC4354aP8IvnGCx4,86316
5
- QuizGenerator/generate.py,sha256=dqF-WWmWxyJmPHl0gTYr3gNNxyF877fvXYaMvYA3uA8,15790
4
+ QuizGenerator/contentast.py,sha256=LEjr-J79ooge0sAlZMuJcyz5Xfj2wRHlAJ_7jAULhBY,87614
5
+ QuizGenerator/generate.py,sha256=qXLJ3WfOo_poIWoAZvEK7epNlVNSWxpOomMVt2MDExA,15816
6
6
  QuizGenerator/misc.py,sha256=MXrguUhhdrWSV4Hqdl4G21ktowODu1AcKy6-5mvy3aI,454
7
- QuizGenerator/mixins.py,sha256=B9Ee52wUCeclmBTgonasHNo0WHvVOcnILsz0iecrf78,15705
7
+ QuizGenerator/mixins.py,sha256=zXj2U94qNbIEusbwTnzRM1Z_zSybpvozWhveq-t5q2Q,15771
8
8
  QuizGenerator/performance.py,sha256=CM3zLarJXN5Hfrl4-6JRBqD03j4BU1B2QW699HAr1Ds,7002
9
9
  QuizGenerator/qrcode_generator.py,sha256=S3mzZDk2UiHiw6ipSCpWPMhbKvSRR1P5ordZJUTo6ug,10776
10
- QuizGenerator/question.py,sha256=cfhCViOSI4p7rcQHE2igv1-aWZgyEKU6rUqJ25VHkfU,32304
10
+ QuizGenerator/question.py,sha256=PKpQ6ZsHkyNw3yJBXlU3akS9Dqhmprq0dLu7wjRzg9A,37240
11
11
  QuizGenerator/quiz.py,sha256=CEWy7FB7BZiK33s_wYs6MqGKDetc6htUaqvP3--2HzI,21621
12
12
  QuizGenerator/regenerate.py,sha256=ZAs1mtERmO8JXza2tBqJpd-uJs9V7gS1jJ9A9gSb8jo,19764
13
13
  QuizGenerator/typst_utils.py,sha256=JGQn_u5bEHd8HAtjAHuZoVJwLkx-Rd4ZCBWffwFZa3o,3136
@@ -15,22 +15,22 @@ QuizGenerator/canvas/__init__.py,sha256=TwFP_zgxPIlWtkvIqQ6mcvBNTL9swIH_rJl7DGKc
15
15
  QuizGenerator/canvas/canvas_interface.py,sha256=StMcdXgLvTA1EayQ44m_le2GXGQpDQnduYXVeUYsqW0,24618
16
16
  QuizGenerator/canvas/classes.py,sha256=v_tQ8t_JJplU9sv2p4YctX45Fwed1nQ2HC1oC9BnDNw,7594
17
17
  QuizGenerator/premade_questions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- QuizGenerator/premade_questions/basic.py,sha256=F_Qsu14b2xERyibCAMP1NPgnmi1h2G2DDkKJoU_RS8g,3284
18
+ QuizGenerator/premade_questions/basic.py,sha256=u6Viv__5HYWjLOknYt_jsBJTej5-cPd9FM1xsuwUQcQ,4613
19
19
  QuizGenerator/premade_questions/cst334/__init__.py,sha256=BTz-Os1XbwIRKqAilf2UIva2NlY0DbA_XbSIggO2Tdk,36
20
20
  QuizGenerator/premade_questions/cst334/languages.py,sha256=ctemEAMkI8C6ASMIf59EHAW1ndFWi7hXzdEt-zOByUE,14114
21
21
  QuizGenerator/premade_questions/cst334/math_questions.py,sha256=aUYbQxneL5MXE7Xo3tZX9-xcg71CXwvG3rrxcoh0l7A,8638
22
22
  QuizGenerator/premade_questions/cst334/memory_questions.py,sha256=g0EFJ2HUogYnOYMWYyn-z4lEv15Pfv5IdSvj0xGoKbI,51050
23
23
  QuizGenerator/premade_questions/cst334/ostep13_vsfs.py,sha256=d9jjrynEw44vupAH_wKl57UoHooCNEJXaC5DoNYualk,16163
24
24
  QuizGenerator/premade_questions/cst334/persistence_questions.py,sha256=9mgsX-3oWDQgm_n2YwmFSil0QPyzsruHzuqB-hfGMuA,16220
25
- QuizGenerator/premade_questions/cst334/process.py,sha256=J9sk-tXeuCDFk2hHm_h9XJE40avacQWPNGf92yp4EjA,37682
25
+ QuizGenerator/premade_questions/cst334/process.py,sha256=0SqXkvdxaEJZXJA8fBqheh7F0PL8I6xgO5a8u2s2po4,37238
26
26
  QuizGenerator/premade_questions/cst463/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  QuizGenerator/premade_questions/cst463/gradient_descent/__init__.py,sha256=sH2CUV6zK9FT3jWTn453ys6_JTrUKRtZnU8hK6RmImU,240
28
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py,sha256=laBeC0tMc2EaLzCotGHQNzePPPOKS1EGgQirigNyi9M,13479
29
- QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py,sha256=_2HlC0sqfGy__Qyzbw0PwMD_OkQiiQukl72LQFyPYx0,10939
30
- QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py,sha256=8GtJX1DNNox-AgMvABFkRgmHB-lvrxMZKzv-3Ils_Jg,22380
28
+ QuizGenerator/premade_questions/cst463/gradient_descent/gradient_calculation.py,sha256=y_R26wUt7AIZVUoe3e_qpzkPdwMyo3mZjxLI504-YQw,13840
29
+ QuizGenerator/premade_questions/cst463/gradient_descent/gradient_descent_questions.py,sha256=OssybIkHx4l8ryHGT9rqHUecta9qpItK4QYVHuuQLeo,11525
30
+ QuizGenerator/premade_questions/cst463/gradient_descent/loss_calculations.py,sha256=slNXfEeLRRM8IDhn3TSQdUWjAimDIfbgUSEmb48zCuU,24156
31
31
  QuizGenerator/premade_questions/cst463/gradient_descent/misc.py,sha256=0R-nFeD3zsqJyde5CXWrF6Npjmpx6_HbzfCbThLi3os,2657
32
32
  QuizGenerator/premade_questions/cst463/math_and_data/__init__.py,sha256=EbIaUrx7_aK9j3Gd8Mk08h9GocTq_0OoNu2trfNwaU8,202
33
- QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py,sha256=4HsMflR1Fm-yjD0J3iW057_q3UHDRiW-swzOd5D73Ys,15647
33
+ QuizGenerator/premade_questions/cst463/math_and_data/matrix_questions.py,sha256=4DLdo_8XDS_xtPA8R-wH4K0cKnMn4r5727Vszz8keTc,15565
34
34
  QuizGenerator/premade_questions/cst463/math_and_data/vector_questions.py,sha256=VXQCLQEeNKxRDPn_fGW5nAPX-0betrZ8mURh0ElbNz0,12668
35
35
  QuizGenerator/premade_questions/cst463/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  QuizGenerator/premade_questions/cst463/models/attention.py,sha256=iECxOoR0LEJAH_d7ZE3MoLOkdYVbGOKo4Dwf8Pww0tM,5443
@@ -40,11 +40,11 @@ QuizGenerator/premade_questions/cst463/models/rnns.py,sha256=5fKQuWnpSAoznZVJuCY
40
40
  QuizGenerator/premade_questions/cst463/models/text.py,sha256=BnW6qIB8pnQiFRyXxtX9cdsIfmjw99p6TI0WqI0AQzk,6605
41
41
  QuizGenerator/premade_questions/cst463/models/weight_counting.py,sha256=sFnEvSs7ZwR4RZPltiMEElKJgoxHTaY427_g8Abi2uk,6912
42
42
  QuizGenerator/premade_questions/cst463/neural-network-basics/__init__.py,sha256=pmyCezO-20AFEQC6MR7KnAsaU9TcgZYsGQOMVkRZ-U8,149
43
- QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py,sha256=bit_HfAG4K6yh9SZZw_HAPhFUVFkOBdZ2odwt-Cdvmo,42868
43
+ QuizGenerator/premade_questions/cst463/neural-network-basics/neural_network_questions.py,sha256=j2f5LFmme-2rSgJzcb8nZJ1_hnZaL-S4lXSnIbpoH_E,43010
44
44
  QuizGenerator/premade_questions/cst463/tensorflow-intro/__init__.py,sha256=G1gEHtG4KakYgi8ZXSYYhX6bQRtnm2tZVGx36d63Nmo,173
45
- QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py,sha256=jZRbEqb65BAtliv_V9VR4kvpwOt-o10ApN7RmOIg3XI,30464
46
- quizgenerator-0.8.0.dist-info/METADATA,sha256=W3Cb-jkrgfxtWGBJ7zynREY_q-_3q53rKpQ0eFC9OCw,8113
47
- quizgenerator-0.8.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
48
- quizgenerator-0.8.0.dist-info/entry_points.txt,sha256=aOIdRdw26xY8HkxOoKHBnUPe2mwGv5Ti3U1zojb6zxQ,98
49
- quizgenerator-0.8.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
50
- quizgenerator-0.8.0.dist-info/RECORD,,
45
+ QuizGenerator/premade_questions/cst463/tensorflow-intro/tensorflow_questions.py,sha256=t0ghv6o8AsZaIwVHFu07Ozebwuv6Rf18D3g_-Jz4O74,31309
46
+ quizgenerator-0.9.0.dist-info/METADATA,sha256=84oI93hpRcDQO03t5qMjloNUWcCQo9MgOZmkMe9YrbY,8177
47
+ quizgenerator-0.9.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
48
+ quizgenerator-0.9.0.dist-info/entry_points.txt,sha256=aOIdRdw26xY8HkxOoKHBnUPe2mwGv5Ti3U1zojb6zxQ,98
49
+ quizgenerator-0.9.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
50
+ quizgenerator-0.9.0.dist-info/RECORD,,