excel2moodle 0.3.2__py3-none-any.whl → 0.3.4__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.
excel2moodle/__init__.py CHANGED
@@ -1,14 +1,20 @@
1
1
  """This Python program helps to create Moodle questions in less time.
2
2
 
3
- The aim is to put alle the information for the questions into a spreadsheet file, and then parse it, to generate Moodle compliant XML-Files.
4
- Furthermore this program lets you create a single ``.xml``-File with a selection of questions, that then can be imported to a Moodle-Test.
3
+ The aim is to put alle the information for the questions into a spreadsheet
4
+ file, and then parse it, to generate Moodle compliant XML-Files.
5
+ Furthermore this program lets you create a single ``.xml``-File with a selection
6
+ of questions, that then can be imported to a Moodle-Test.
5
7
 
6
8
  Concept
7
9
  =========
8
- The concept is, to store the different questions into categories of similar types and difficulties of questions, for each of which, a separated sheet in the Spreadsheet document should be created.
10
+ The concept is, to store the different questions into categories of similar
11
+ types and difficulties of questions, for each of which, a separated sheet in
12
+ the Spreadsheet document should be created.
9
13
 
10
- There Should be a sheet called *"Kategorien"*, where an overview over the different categories is stored.
11
- This sheet stores The names and descriptions, for all categories. The name have to be the same as the actual sheet names with the questions.
14
+ There Should be a sheet called *"Kategorien"*, where an overview over the
15
+ different categories is stored.
16
+ This sheet stores The names and descriptions, for all categories.
17
+ The name have to be the same as the actual sheet names with the questions.
12
18
  Furthermore the points used for grading, are set in the "Kategorien" sheet
13
19
 
14
20
  Functionality
@@ -17,12 +23,34 @@ Functionality
17
23
  * Parse Numeric Questions, each into one XML file
18
24
  * create single XML File from a selection of questions
19
25
  """
26
+
27
+ from importlib import metadata
20
28
  from importlib.metadata import version
29
+
21
30
  try:
22
31
  __version__ = version("excel2moodle")
23
32
  except Exception:
24
33
  __version__ = "unknown"
25
34
 
35
+
36
+ if __package__ is not None:
37
+ meta = metadata.metadata(__package__)
38
+ e2mMetadata: dict = {
39
+ "version": __version__,
40
+ "name": meta["name"],
41
+ "description": meta["summary"],
42
+ "author": meta["author"],
43
+ "license": meta["license-expression"],
44
+ "documentation": "https://jbosse3.gitlab.io/excel2moodle",
45
+ "homepage": meta["project-url"].split()[1],
46
+ "issues": "https://gitlab.com/jbosse3/excel2moodle/issues",
47
+ }
48
+
49
+ import logging as logging
50
+ from logging import config as logConfig
51
+
52
+ from PySide6.QtCore import QObject, Signal
53
+
26
54
  # from excel2moodle.core import klausurGenerator
27
55
  # from excel2moodle.core import numericMultiQ
28
56
  # from excel2moodle.core import questionWriter
@@ -33,68 +61,63 @@ except Exception:
33
61
  # from excel2moodle.ui import kGeneratorQt
34
62
  from excel2moodle.ui import settings
35
63
 
36
- from PySide6.QtCore import QObject, Signal
37
- import logging as logging
38
- from logging import config as logConfig
39
- from pathlib import Path
40
-
41
64
  loggerConfig = {
42
- 'version': 1,
43
- 'disable_existing_loggers': False,
44
- 'formatters': {
45
- 'standard': {
46
- 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
47
- },
65
+ "version": 1,
66
+ "disable_existing_loggers": False,
67
+ "formatters": {
68
+ "standard": {"format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s"},
48
69
  },
49
- 'handlers': {
50
- 'default': {
51
- 'level': 'DEBUG',
52
- 'formatter': 'standard',
53
- 'class': 'logging.StreamHandler',
54
- 'stream': 'ext://sys.stdout', # Default is stderr
70
+ "handlers": {
71
+ "default": {
72
+ "level": "DEBUG",
73
+ "formatter": "standard",
74
+ "class": "logging.StreamHandler",
75
+ "stream": "ext://sys.stdout", # Default is stderr
55
76
  },
56
77
  },
57
- 'loggers': {
58
- '': { # root logger
59
- 'handlers': ['default'],
60
- 'level': 'DEBUG',
61
- 'propagate': True
78
+ "loggers": {
79
+ "": { # root logger
80
+ "handlers": ["default"],
81
+ "level": "DEBUG",
82
+ "propagate": True,
62
83
  },
63
- 'excel2moodle.questionParser': {
64
- 'handlers': ['default'],
65
- 'level': 'DEBUG',
66
- 'propagate': True
84
+ "excel2moodle.questionParser": {
85
+ "handlers": ["default"],
86
+ "level": "DEBUG",
87
+ "propagate": True,
67
88
  },
68
- '__main__': { # if __name__ == '__main__'
69
- 'handlers': ['default'],
70
- 'level': 'DEBUG',
71
- 'propagate': True
89
+ "__main__": { # if __name__ == '__main__'
90
+ "handlers": ["default"],
91
+ "level": "DEBUG",
92
+ "propagate": True,
72
93
  },
73
- }
94
+ },
74
95
  }
75
96
 
97
+
76
98
  class QSignaler(QObject):
77
99
  signal = Signal(str)
78
100
 
101
+
79
102
  class LogHandler(logging.Handler):
80
- def __init__(self, *args, **kwargs)->None:
81
- super().__init__(*args,**kwargs)
103
+ def __init__(self, *args, **kwargs) -> None:
104
+ super().__init__(*args, **kwargs)
82
105
  self.emitter = QSignaler()
83
- # Define a formatter with log level and module
106
+ # Define a formatter with log level and module
84
107
  log_format = "[%(levelname)s] %(module)s: %(message)s"
85
108
  self.formatter = logging.Formatter(log_format)
86
109
  self.setFormatter(self.formatter)
87
110
  self.logLevelColors = {
88
- 'DEBUG': 'gray',
89
- 'INFO': 'green',
90
- 'WARNING': 'orange',
91
- 'ERROR': 'red',
92
- 'CRITICAL': 'pink'
111
+ "DEBUG": "gray",
112
+ "INFO": "green",
113
+ "WARNING": "orange",
114
+ "ERROR": "red",
115
+ "CRITICAL": "pink",
93
116
  }
94
117
 
95
- def emit(self, record)->None:
118
+ def emit(self, record) -> None:
96
119
  log_message = self.format(record)
97
- color = self.logLevelColors.get(record.levelname, 'black')
120
+ color = self.logLevelColors.get(record.levelname, "black")
98
121
  prettyMessage = f'<span style="color:{color};">{log_message}</span>'
99
122
  self.emitter.signal.emit(prettyMessage)
100
123
  return None
@@ -108,6 +131,6 @@ logging.config.dictConfig(config=loggerConfig)
108
131
  qSignalLogger = LogHandler()
109
132
  logger.addHandler(qSignalLogger)
110
133
 
111
- p = Path(__file__).parent
112
- dirProjectRoot = p.parent.resolve()
113
- dirDocumentation = (dirProjectRoot / "docs/_build/html")
134
+
135
+ for k, v in e2mMetadata.items():
136
+ print(f"{k}: \t {v}\n")
excel2moodle/__main__.py CHANGED
@@ -1,31 +1,21 @@
1
1
  """Main Function to make the Package executable"""
2
2
 
3
- from pathlib import Path
4
-
5
3
  from PySide6 import QtWidgets, sys
6
- import xml.etree.ElementTree as xmlET
7
4
 
8
- from excel2moodle.core import dataStructure
5
+ from excel2moodle.core import dataStructure
9
6
  from excel2moodle.ui import appUi as ui
10
7
  from excel2moodle.ui.settings import Settings
11
8
 
12
- import logging
13
-
14
- katOutPath = None
15
- excelFile = None
16
-
17
- logger = logging.getLogger(__name__)
18
9
 
19
-
20
- def main()->None:
10
+ def main() -> None:
21
11
  app = QtWidgets.QApplication(sys.argv)
22
12
  settings = Settings()
23
- database:dataStructure.QuestionDB = dataStructure.QuestionDB(settings)
13
+ database: dataStructure.QuestionDB = dataStructure.QuestionDB(settings)
24
14
  window = ui.MainWindow(settings, database)
25
15
  database.window = window
26
16
  window.show()
27
17
  sys.exit(app.exec())
28
18
 
29
- if __name__ =="__main__":
30
- main()
31
19
 
20
+ if __name__ == "__main__":
21
+ main()
@@ -1,27 +1,38 @@
1
-
2
1
  import logging
3
- import pandas as pd
2
+
4
3
  import lxml.etree as ET
4
+ import pandas as pd
5
5
 
6
- from excel2moodle.core.exceptions import InvalidFieldException
7
- from excel2moodle.core.questionValidator import Validator
8
- logger = logging.getLogger(__name__)
6
+ from excel2moodle.core.parser import (
7
+ MCQuestionParser,
8
+ NFMQuestionParser,
9
+ NFQuestionParser,
10
+ QNotParsedException,
11
+ )
9
12
  from excel2moodle.core.question import Question
10
13
 
11
- from excel2moodle.core.globals import XMLTags, TextElements, DFIndex, questionTypes, parserSettings
12
- from excel2moodle.core.parser import NFMQuestionParser, NFQuestionParser, MCQuestionParser, QNotParsedException
14
+ logger = logging.getLogger(__name__)
13
15
 
14
- class Category():
15
- def __init__(self, n:int, name:str, description:str, dataframe: pd.DataFrame, points:float=0, version:int=0)->None:
16
+
17
+ class Category:
18
+ def __init__(
19
+ self,
20
+ n: int,
21
+ name: str,
22
+ description: str,
23
+ dataframe: pd.DataFrame,
24
+ points: float = 0,
25
+ version: int = 0,
26
+ ) -> None:
16
27
  self.n = n
17
28
  self.NAME = name
18
29
  self.desc = str(description)
19
- self.dataframe:pd.DataFrame = dataframe
30
+ self.dataframe: pd.DataFrame = dataframe
20
31
  self.points = points
21
32
  self.version = int(version)
22
- self.questions:dict[int,Question] = {}
23
- self.maxVariants:int|None = None
24
- logger.info(f"initializing {self.NAME =}")
33
+ self.questions: dict[int, Question] = {}
34
+ self.maxVariants: int | None = None
35
+ logger.info(f"initializing {self.NAME=}")
25
36
 
26
37
  @property
27
38
  def name(self):
@@ -39,70 +50,50 @@ class Category():
39
50
  return self.NAME == other.NAME
40
51
  return False
41
52
 
42
- def _getQuestions(self)->None:
43
- self.questions:dict[int,Question] = {}
44
- validator = Validator(self)
45
- for q in self.dataframe.columns:
46
- logger.debug(f"Starting to check Validity of {q}")
47
- qdat = self.dataframe[q]
48
- if isinstance(qdat, pd.Series):
49
- validator.setup(qdat, q)
50
- check = False
51
- try:
52
- check = validator.validate()
53
- except InvalidFieldException as e:
54
- logger.error(f"Frage {self.id}{q:02d} ist invalid.", exc_info=e)
55
- if check:
56
- self.questions[q]=validator.question
57
- try:
58
- self.parseQ(self.questions[q])
59
- except QNotParsedException as e:
60
- logger.error(f"Frage {self.questions[q].id} konnte nicht erstellt werden", exc_info=e)
61
- return None
62
-
63
- def parsAll(self, tree: ET.Element = None)->None:
64
- if tree is None:
65
- tree = ET.Element("quiz")
66
- tree.append(self.getCategoryHeader())
67
- for q in self.questions.values():
68
- self.parseQ(q, tree)
69
-
70
- def parseQ(self, q:Question, xmlTree:ET._Element|None=None)->bool:
53
+ def parseQ(
54
+ self,
55
+ q: Question,
56
+ questionData: dict | None = None,
57
+ xmlTree: ET._Element | None = None,
58
+ ) -> bool:
71
59
  if q.element is not None:
72
60
  logger.info(f"Question {q.id} is already parsed")
73
61
  return True
74
62
  else:
75
- series = self.dataframe[q.number]
76
63
  if q.qtype == "NF":
77
- parser = NFQuestionParser( q, series)
78
- logger.debug(f"setup a new NF parser ")
64
+ parser = NFQuestionParser(q, questionData)
65
+ logger.debug("setup a new NF parser ")
79
66
  elif q.qtype == "MC":
80
- parser = MCQuestionParser( q, series)
81
- logger.debug(f"setup a new MC parser ")
67
+ parser = MCQuestionParser(q, questionData)
68
+ logger.debug("setup a new MC parser ")
82
69
  elif q.qtype == "NFM":
83
- parser = NFMQuestionParser( q, series)
84
- logger.debug(f"setup a new NFM parser ")
85
- else:
86
- logger.error(f"ERROR, couldn't setup Parser")
70
+ parser = NFMQuestionParser(q, questionData)
71
+ logger.debug("setup a new NFM parser ")
72
+ else:
73
+ logger.error("ERROR, couldn't setup Parser")
87
74
  return False
88
75
  try:
89
76
  parser.parse(xmlTree=xmlTree)
90
77
  return True
91
78
  except QNotParsedException as e:
92
- logger.critical(f"The Question {q.id} couldn't be parsed", exc_info=e, stack_info=True)
79
+ logger.critical(
80
+ f"The Question {q.id} couldn't be parsed",
81
+ exc_info=e,
82
+ stack_info=True,
83
+ )
93
84
  return False
94
85
  finally:
95
86
  del parser
96
87
 
97
- def getCategoryHeader(self)->ET.Element:
98
- """vor den Fragen einer Kategorie wird ein <question type='category'> eingefügt mit Name und Beschreibung"""
99
- header = ET.Element('question', type='category')
100
- cat = ET.SubElement(header,"category")
101
- info = ET.SubElement(header,"info", format='html')
102
- ET.SubElement(cat,"text").text = f"$module$/top/{self.NAME}"
103
- ET.SubElement(info,"text").text = str(self.desc)
104
- ET.SubElement(header,"idnumber").text = str(self.n)
88
+ def getCategoryHeader(self) -> ET.Element:
89
+ """vor den Fragen einer Kategorie wird ein
90
+ <question type='category'> eingefügt mit Name und Beschreibung
91
+ """
92
+ header = ET.Element("question", type="category")
93
+ cat = ET.SubElement(header, "category")
94
+ info = ET.SubElement(header, "info", format="html")
95
+ ET.SubElement(cat, "text").text = f"$module$/top/{self.NAME}"
96
+ ET.SubElement(info, "text").text = str(self.desc)
97
+ ET.SubElement(header, "idnumber").text = str(self.n)
105
98
  ET.indent(header)
106
99
  return header
107
-
108
-
@@ -1,86 +1,100 @@
1
- """Main Module which does the heavy lifting
1
+ """Main Module which does the heavy lifting
2
2
 
3
3
  At the heart is the class ``xmlTest``
4
4
  """
5
5
 
6
+ import logging
6
7
  from pathlib import Path
7
- from PySide6 import QtCore
8
- from PySide6 import QtWidgets
8
+
9
+ import lxml.etree as ET
10
+ import pandas as pd
11
+ from PySide6 import QtCore, QtWidgets
9
12
  from PySide6.QtCore import Signal
10
13
  from PySide6.QtWidgets import QMainWindow, QMessageBox, QTreeWidget
11
- import pandas as pd
12
- import lxml.etree as ET
13
- import logging
14
14
 
15
15
  from excel2moodle import QSignaler
16
16
  from excel2moodle.core import stringHelpers
17
17
  from excel2moodle.core.category import Category
18
- from excel2moodle.ui.dialogs import QuestionVariantDialog
19
- from excel2moodle.ui.treewidget import QuestionItem, CategoryItem
18
+ from excel2moodle.core.exceptions import InvalidFieldException, QNotParsedException
19
+ from excel2moodle.core.question import Question
20
20
  from excel2moodle.core.questionValidator import Validator
21
+ from excel2moodle.ui.dialogs import QuestionVariantDialog
21
22
  from excel2moodle.ui.settings import Settings
22
- from excel2moodle.core.question import Question
23
- from excel2moodle.core.exceptions import InvalidFieldException, QNotParsedException
24
-
23
+ from excel2moodle.ui.treewidget import CategoryItem, QuestionItem
25
24
 
26
25
  logger = logging.getLogger(__name__)
27
26
 
28
27
 
29
- class QuestionDB():
28
+ class QuestionDB:
30
29
  """oberste Klasse für den Test"""
30
+
31
31
  dataChanged = QSignaler()
32
32
 
33
- def __init__(self, settings:Settings):
33
+ def __init__(self, settings: Settings):
34
34
  self.settings = settings
35
35
  self.spreadSheetPath = Path()
36
36
  self.mainPath = Path()
37
- self.window:QMainWindow|None = None
37
+ self.window: QMainWindow | None = None
38
38
  self.version = None
39
39
  self.categoriesMetaData = pd.DataFrame()
40
- self.categories:dict[str,Category]={}
40
+ self.categories: dict[str, Category] = {}
41
41
  self.settings.shPathChanged.connect(self.onSheetPathChanged)
42
42
 
43
43
  @QtCore.Slot(Path)
44
- def onSheetPathChanged(self, sheet:Path)->None:
44
+ def onSheetPathChanged(self, sheet: Path) -> None:
45
45
  logger.debug("Slot, new Spreadsheet triggered")
46
46
  self.spreadSheetPath = sheet
47
- self.svgFolder = (self.spreadSheetPath.parent / 'Abbildungen_SVG')
47
+ svgFolder = self.spreadSheetPath.parent / str(
48
+ self.settings.get("core/pictureSubFolder", default="Abbildungen_SVG")
49
+ )
50
+ svgFolder.resolve()
51
+ self.settings.set("core/pictureFolder", svgFolder)
48
52
  self.retrieveCategoriesData()
49
53
  self.parseAll()
50
54
 
51
- def retrieveCategoriesData(self)->None:
52
- """Scans through the sheet with the metadata for all the question categories
55
+ def retrieveCategoriesData(self) -> None:
56
+ """Scans through the sheet with the metadata for all categories
53
57
 
54
- The information that will be shown in the UI like description and points is retrieved from one spreadsheet sheet.
55
- This method gathers this information and stores it in the ``categoriesMetaData`` dataframe
58
+ The information that will be shown in the UI like description
59
+ and points is retrieved from one spreadsheet sheet.
60
+ This method gathers this information and stores it in the
61
+ ``categoriesMetaData`` dataframe
56
62
  """
57
63
 
58
64
  logger.info("Start Parsing the Excel Metadata Sheet\n")
59
- with open(self.spreadSheetPath, 'rb') as f:
65
+ with open(self.spreadSheetPath, "rb") as f:
60
66
  excelFile = pd.ExcelFile(f)
61
- self.categoriesMetaData = pd.read_excel(f, sheet_name="Kategorien",
62
- usecols=["Kategorie", "Beschreibung", "Punkte", "Version"],
63
- index_col=0)
67
+ self.categoriesMetaData = pd.read_excel(
68
+ f,
69
+ sheet_name="Kategorien",
70
+ usecols=["Kategorie", "Beschreibung", "Punkte", "Version"],
71
+ index_col=0,
72
+ )
64
73
  logger.info("Sucessfully read categoriesMetaData")
65
74
  print(self.categoriesMetaData)
75
+ self.categories = {}
66
76
  for sh in excelFile.sheet_names:
67
77
  if sh.startswith("KAT"):
68
78
  n = int(sh[4:])
69
- katDf = pd.read_excel(f, sheet_name=str(sh), index_col=0, header=None)
79
+ katDf = pd.read_excel(
80
+ f, sheet_name=str(sh), index_col=0, header=None
81
+ )
70
82
  if not katDf.empty:
71
- p = self.categoriesMetaData["Punkte"].iloc[n-1]
72
- points = (p if not pd.isna(p) else 1)
73
- v = self.categoriesMetaData["Version"].iloc[n-1]
74
- version = (v if not pd.isna(v) else 0)
75
- self.categories[sh] = Category(n,sh,
76
- self.categoriesMetaData["Beschreibung"].iloc[n-1],
77
- dataframe=katDf,
78
- points=points,
79
- version=version)
83
+ p = self.categoriesMetaData["Punkte"].iloc[n - 1]
84
+ points = p if not pd.isna(p) else 1
85
+ v = self.categoriesMetaData["Version"].iloc[n - 1]
86
+ version = v if not pd.isna(v) else 0
87
+ self.categories[sh] = Category(
88
+ n,
89
+ sh,
90
+ self.categoriesMetaData["Beschreibung"].iloc[n - 1],
91
+ dataframe=katDf,
92
+ points=points,
93
+ version=version,
94
+ )
80
95
  self.dataChanged.signal.emit("whoo")
81
96
  return None
82
97
 
83
-
84
98
  def parseAll(self):
85
99
  self.mainTree = ET.Element("quiz")
86
100
  for c in self.categories.values():
@@ -94,17 +108,25 @@ class QuestionDB():
94
108
  try:
95
109
  check = validator.validate()
96
110
  except InvalidFieldException as e:
97
- logger.error(f"Question {c.id}{q:02d} is invalid.", exc_info=e)
98
- if check:
99
- c.questions[q]=validator.question
111
+ logger.error(
112
+ f"Question {c.id}{
113
+ q:02d} is invalid.",
114
+ exc_info=e,
115
+ )
116
+ if check:
117
+ c.questions[q] = validator.question
100
118
  try:
101
- c.parseQ(c.questions[q])
119
+ c.parseQ(c.questions[q], validator.qdata)
102
120
  except QNotParsedException as e:
103
- logger.error(f"Frage {c.questions[q].id} konnte nicht erstellt werden", exc_info=e)
121
+ logger.error(
122
+ f"Frage {
123
+ c.questions[q].id} konnte nicht erstellt werden",
124
+ exc_info=e,
125
+ )
104
126
 
105
- def appendQuestions(self, questions:list[QuestionItem], file:Path|None=None):
127
+ def appendQuestions(self, questions: list[QuestionItem], file: Path | None = None):
106
128
  tree = ET.Element("quiz")
107
- catdict:dict[Category,list[Question]]={}
129
+ catdict: dict[Category, list[Question]] = {}
108
130
  for q in questions:
109
131
  logger.debug(f"got a question to append {q=}")
110
132
  cat = q.parent().getCategory()
@@ -113,13 +135,25 @@ class QuestionDB():
113
135
  print(f"Category is parent of Q {cat=}")
114
136
  catdict[cat].append(q.getQuestion())
115
137
  for cat, qlist in catdict.items():
116
- print(f"{cat = }, mit fragen {qlist = }")
117
- self.appendQElements(cat, qlist, tree=tree, includeHeader=self.settings.value("testGen/includeCats"))
138
+ print(f"{cat=}, mit fragen {qlist=}")
139
+ self.appendQElements(
140
+ cat,
141
+ qlist,
142
+ tree=tree,
143
+ includeHeader=self.settings.value("testGen/includeCats"),
144
+ )
118
145
  stringHelpers.printDom(tree, file=file)
119
146
 
120
- def appendQElements(self,cat:Category, qList:list[Question], tree:ET.Element, includeHeader:bool=True)->None:
147
+ def appendQElements(
148
+ self,
149
+ cat: Category,
150
+ qList: list[Question],
151
+ tree: ET.Element,
152
+ includeHeader: bool = True,
153
+ ) -> None:
121
154
  if includeHeader:
122
- tree.append( cat.getCategoryHeader())
155
+ tree.append(cat.getCategoryHeader())
156
+ logger.debug(f"Appended a new category item {cat=}")
123
157
  sameVariant = False
124
158
  variant = 1
125
159
  for q in qList:
@@ -132,10 +166,11 @@ class QuestionDB():
132
166
  sameVariant = dialog.categoryWide
133
167
  logger.debug(f"Die Fragen-Variante {variant} wurde gewählt")
134
168
  q.assemble(variant)
135
- else: print("skipping this question")
136
- q.assemble
169
+ else:
170
+ print("skipping this question")
171
+ else:
172
+ q.assemble()
137
173
  tree.append(q.element)
138
- else: logger.warning(f"Frage {q} wurde nicht erstellt")
174
+ else:
175
+ logger.warning(f"Frage {q} wurde nicht erstellt")
139
176
  return None
140
-
141
-
@@ -4,29 +4,31 @@ This module host different functions. All of them will return an ``lxml.etree.El
4
4
  """
5
5
 
6
6
  import lxml.etree as ET
7
- from .globals import DFIndex, XMLTags
8
- import pandas as pd
9
- from excel2moodle.core.globals import feedbackStr, TextElements, feedBElements
7
+
10
8
  import excel2moodle.core.etHelpers as eth
9
+ from excel2moodle.core.globals import TextElements, feedbackStr, feedBElements
10
+
11
+ from .globals import DFIndex, XMLTags
12
+
11
13
 
12
- def getElement( eleName : str, text: str, **attribs)->ET.Element:
14
+ def getElement(eleName: str, text: str, **attribs) -> ET.Element:
13
15
  """Creates an XML-Element with text
14
-
16
+
15
17
  If ``type(text)``is a ``QuestionFields``, the specific field is directly read.
16
18
  Otherwise it will include whatever is ``text`` as a string
17
19
  :param **kwargs: are treated as attributes for the Element
18
- raises:
20
+ raises:
19
21
  NanException if the spreadsheet cell of text:QuestionFields is ``nan``
20
22
  """
21
23
 
22
24
  toEle = ET.Element(eleName)
23
25
  toEle.text = str(text)
24
26
  for k, v in attribs.items():
25
- toEle.set(k,v)
27
+ toEle.set(k, v)
26
28
  return toEle
27
29
 
28
30
 
29
- def getTextElement( eleName:str, text:str|DFIndex, **attribs)->ET.Element:
31
+ def getTextElement(eleName: str, text: str | DFIndex, **attribs) -> ET.Element:
30
32
  """Creates two nested elements: ``eleName`` with child ``text`` which holds the text"""
31
33
 
32
34
  toEle = ET.Element(eleName, **attribs)
@@ -34,28 +36,31 @@ def getTextElement( eleName:str, text:str|DFIndex, **attribs)->ET.Element:
34
36
  toEle.append(child)
35
37
  return toEle
36
38
 
37
- def getCdatTxtElement(subEle: ET._Element|list[ET._Element])->ET.Element:
39
+
40
+ def getCdatTxtElement(subEle: ET._Element | list[ET._Element]) -> ET.Element:
38
41
  """Puts all ``subEle`` as ``str`` into a ``<text><![CDATA[...subEle...]]</text>`` element"""
39
42
 
40
43
  textEle = ET.Element(XMLTags.TEXT)
41
44
  if isinstance(subEle, list):
42
- elementString : list= []
45
+ elementString: list = []
43
46
  for i in subEle:
44
47
  elementString.append(ET.tostring(i, encoding="unicode", pretty_print=True))
45
48
  textEle.text = ET.CDATA("".join(elementString))
46
49
  return textEle
47
50
  else:
48
- textEle.text = ET.CDATA(ET.tostring(subEle, encoding="unicode", pretty_print=True))
49
- return textEle
51
+ textEle.text = ET.CDATA(
52
+ ET.tostring(subEle, encoding="unicode", pretty_print=True)
53
+ )
54
+ return textEle
50
55
 
51
56
 
52
- def getFeedBEle(feedback:XMLTags,
53
- text:str|None=None, style: TextElements | None = None
54
- )->ET.Element:
57
+ def getFeedBEle(
58
+ feedback: XMLTags, text: str | None = None, style: TextElements | None = None
59
+ ) -> ET.Element:
55
60
  """Gets ET Elements with the feedback for the question."""
56
61
  if style is None:
57
62
  span = feedBElements[feedback]
58
- else:
63
+ else:
59
64
  span = style.create()
60
65
  if text is None:
61
66
  text = feedbackStr[feedback]