excel2moodle.core package — excel2moodle 0.5.0 documentation

# excel2moodle.core package

These Modules are the heart of the excel2moodle Package.

## Submodules

## excel2moodle.core.category module

class excel2moodle.core.category.Category(name, description, dataframe, settings)

  Bases: `object`

  Category stores a list of question. And holds shared information for all.

  Parameters:

    - name (str)

    - description (str)

    - dataframe (DataFrame)

    - settings (dict[str, float | str])

  getCategoryHeader()

    Insert an <question type=’category’> before all Questions of this Category.

    Return type:

      `Element`

  property id: str
  property name: str
  property points: float

## excel2moodle.core.dataStructure module

Main Module which does the heavy lifting.

At the heart is the class `xmlTest`

class excel2moodle.core.dataStructure.QuestionDB(settings)

  Bases: `object`

  The QuestionDB is the main class for processing the Spreadsheet.

  It provides the functionality, for setting up the categories and Questions. Any interaction with the questions are done by its methods.

  Parameters:

    settings (Settings)

  appendQuestions(questions, file=None)

    Append selected question Elements to the tree.

    Return type:

      `None`

    Parameters:

      - questions (list[QuestionItem])

      - file (Path | None)

  asyncInitAllCategories(sheetPath=None)

    Read all category sheets asynchron and initialize all Categories.

    It does the same as initAllCategories but the parsing of the excelfile is done asynchron via concurrent.futures.ProcessPoolExecutor

    Return type:

      `None`

    Parameters:

      sheetPath (Path | None)

  clozeParser: `ClozeQuestionParser` = <excel2moodle.question_types.cloze.ClozeQuestionParser object>
  static harmonizeDFIndex(dataframe)

    Convert the index strings to lowercase without whitespace.

    Return type:

      `DataFrame`

    Parameters:

      dataframe (DataFrame)

  initAllCategories(sheetPath=None)

    Read all category sheets and initialize all Categories.

    Return type:

      `None`

    Parameters:

      sheetPath (Path | None)

  initCategory(categoryName, sheetPath=None)

    Read categoryName from the `sheetPath` and initialize the category. Returns the Category and appends it to self.categories.

    Return type:

      `bool` | `Category`

    Parameters:

      - categoryName (str)

      - sheetPath (Path | None)

  mcParser: `MCQuestionParser` = <excel2moodle.question_types.mc.MCQuestionParser object>
  nfParser: `NFQuestionParser` = <excel2moodle.question_types.nf.NFQuestionParser object>
  nfmParser: `NFMQuestionParser` = <excel2moodle.question_types.nfm.NFMQuestionParser object>
  parseAllQuestions()

    Parse all question from all categories.

    The categories need to be initialized first.

    Return type:

      `None`

  parseCategoryQuestions(category)

    Parse all questions inside `category`.

    The category has to be initialized first.

    Return type:

      `None`

    Parameters:

      category (Category)

  readCategoriesMetadata(sheetPath=None)

    Read the metadata and questions from the spreadsheet.

    Get the category data from the spreadsheet and stores it in the `categoriesMetaData` dataframe Setup the categories and store them in `self.categories = {}` Pass the question data to the categories.

    Return type:

      `DataFrame`

    Parameters:

      sheetPath (Path | None)

  classmethod setupAndParseQuestion(category, qNumber)

    Check if the Question Data is valid. Then parse it.

    The Question data is accessed from category.dataframe via its number First it is checked if all mandatory fields for the given question type are provided. Then in checks, weather the data has the correct type. If the data is valid, the corresponding parser is fed with the data and run.

    Raises:

      - QNotParsedException – If the parsing of the question is not possible this is raised

      - InvalidFieldException – If the data of the question is invalid. This gives more information wheather a missing field, or the invalid type caused the Exception.

    Return type:

      `Question` | `None`

    Parameters:

      - category (Category)

      - qNumber (int)

  signals = <excel2moodle.core.dataStructure.QuestionDBSignals(0x564e5d816430)>
  property spreadsheet: Path
  validator: `Validator` = <excel2moodle.core.validator.Validator object>

class excel2moodle.core.dataStructure.QuestionDBSignals

  Bases: `QObject`

  categoryQuestionsReady
  categoryReady
  staticMetaObject = PySide6.QtCore.QMetaObject("QuestionDBSignals" inherits "QObject": Methods: #4 type=Signal, signature=categoryReady(PyObject), parameters=PyObject #5 type=Signal, signature=categoryQuestionsReady(PyObject), parameters=PyObject )

excel2moodle.core.dataStructure.processSheet(sheetPath, categoryName)

  Parse categoryName from the file `sheetPath` into the dataframe.

  This Function is meant to be run asynchron for increased speed.

  Return type:

    `DataFrame`

  Parameters:

    - sheetPath (str)

    - categoryName (str)

## excel2moodle.core.etHelpers module

Helper Module which aids in creating XML-Elements for the Questions.

This module host different functions. All of them will return an `lxml.etree.Element`

excel2moodle.core.etHelpers.getCdatTxtElement(subEle)

  Puts all `subEle` as `str` into a `<text><![CDATA[...subEle...]]</text>` element.

  Return type:

    `Element`

  Parameters:

    subEle (_Element | list[_Element])

excel2moodle.core.etHelpers.getElement(eleName, text, **attribs)

  Creates an XML-Element with text.

  If `type(text)``is a ``QuestionFields`, the specific field is directly read. Otherwise it will include whatever is `text` as a string :param **kwargs: are treated as attributes for the Element :raises NanException if the spreadsheet cell of text: QuestionFields is `nan`

  Return type:

    `Element`

  Parameters:

    - eleName (str)

    - text (str)

excel2moodle.core.etHelpers.getFeedBEle(feedback, text=None, style=None)

  Gets ET Elements with the feedback for the question.

  Return type:

    `Element`

  Parameters:

    - feedback (XMLTags)

    - text (str | None)

    - style (TextElements | None)

excel2moodle.core.etHelpers.getTextElement(eleName, text, **attribs)

  Creates two nested elements: `eleName` with child `text` which holds the text.

  Return type:

    `Element`

  Parameters:

    - eleName (str)

    - text (str | Tags)

## excel2moodle.core.exceptions module

exception excel2moodle.core.exceptions.InvalidFieldException(message, qID, field, *args, **kwargs)

  Bases: `Exception`

  Parameters:

    - message (str)

    - qID (str)

    - field (Tags | list[Tags])

    - args (object)

  Return type:

    None

exception excel2moodle.core.exceptions.NanException(message, qID, field, *args, **kwargs)

  Bases: `QNotParsedException`

  Return type:

    None

exception excel2moodle.core.exceptions.QNotParsedException(message, qID, *args, **kwargs)

  Bases: `Exception`

  Parameters:

    - message (str)

    - qID (str | int)

  Return type:

    None

## excel2moodle.core.globals module

class excel2moodle.core.globals.TextElements(*values)

  Bases: `Enum`

  LISTITEM = ('li', 'text-align: left;')
  PLEFT = ('p', 'text-align: left;')
  SPANGREEN = ('span', 'color: rgb(152, 202, 62)')
  SPANORANGE = ('span', 'color: rgb(152, 100, 100)')
  SPANRED = ('span', 'color: rgb(239, 69, 64)')
  ULIST = ('ul', '')
  create(tag=None)
    Parameters:

      tag (str | None)

  property style: str

class excel2moodle.core.globals.XMLTags(_, dfkey=None, getEle=None)

  Bases: `StrEnum`

  ANSFEEDBACK = 'feedback'
  ANSWER = 'answer'
  CORFEEDB = 'correctfeedback'
  GENFEEDB = 'generalfeedback'
  HIDE = 'hidden'
  ID = 'idnumber'
  INCORFEEDB = 'incorrectfeedback'
  NAME = 'name'
  PCORFEEDB = 'partialcorrectfeedback'
  PENALTY = 'penalty'
  PICTURE = 'file'
  POINTS = 'defaultgrade'
  QTEXT = 'questiontext'
  QUESTION = 'question'
  TEXT = 'text'
  TOLERANCE = 'tolerance'
  TYPE = 'type'
  property dfkey: str
  set(getEle)
    Return type:

      `None`

## excel2moodle.core.numericMultiQ module

Numeric Multi Questions Module to calculate results from a formula.

This module calculates a series of results from al matrix of variables. For each column in the matrix there will be one result. As well it returns a bullet points string that shows the numerical values corresponding to the set of variables

excel2moodle.core.numericMultiQ.getVariablesDict(df, keyList, index)

  Liest alle Variablen-Listen deren Name in `keyList` ist aus dem DataFrame im Column[index].

  Return type:

    `dict`

  Parameters:

    - df (DataFrame)

    - keyList (list)

    - index (int)

excel2moodle.core.numericMultiQ.getVarsList(bps)

  Durchsucht den bulletPoints String nach den Variablen {var}.

  Return type:

    `list`

  Parameters:

    bps (str)

excel2moodle.core.numericMultiQ.insertVariablesToBPoints(varDict, bulletPoints, index)

  Für jeden Eintrag im varDict, wird im bulletPoints String der Substring “{key}” durch value[index] ersetzt.

  Return type:

    `str`

  Parameters:

    - varDict (dict)

    - bulletPoints (str)

    - index (int)

excel2moodle.core.numericMultiQ.parseNumericMultiQuestion(datFrame, bulletPoints, equation, questionIndex)

  Berechnet die Ergebnisse anhand der Variablen in bulletPoints.

  Gibt eine Liste mit allen Ergebnissen zurück und eine Liste mit den bulletPoints-Strings, die die Numerischen Variablen enthalten

  Return type:

    `tuple`[`list`[`str`], `list`[`float`]]

  Parameters:

    - datFrame (DataFrame)

    - bulletPoints (str)

    - equation (str)

    - questionIndex (int)

excel2moodle.core.numericMultiQ.setParameters(parameters, index)

  Ubergibt die Parameter mit entsprechenden Variablen-Namen an den asteval-Interpreter.

  Dann kann dieser die equation loesen.

  Return type:

    `None`

  Parameters:

    - parameters (dict)

    - index (int)

## excel2moodle.core.parser module

class excel2moodle.core.parser.QuestionParser

  Bases: `object`

  Setup the Parser Object.

  This is the superclass which implements the general Behaviour of he Parser. Important to implement the answers methods.

  appendToTmpEle(eleName, text, txtEle=False, **attribs)

    Append `text` to the temporary Element.

    It uses the data from `self.rawInput` if `text` is type``DFIndex`` Otherwise the value of `text` will be inserted.

    Return type:

      `None`

    Parameters:

      - eleName (str)

      - text (str | Tags)

  formatBulletList(bps)
    Return type:

      `Element`

    Parameters:

      bps (list[str])

  getFeedBEle(feedback, text=None, style=None)
    Return type:

      `Element`

    Parameters:

      - feedback (XMLTags)

      - text (str | None)

      - style (TextElements | None)

  getNumericAnsElement(result, fraction=100, format='moodle_auto_format')

    Get `<answer/>` Element specific for the numerical Question.

    Return type:

      `Element`

    Parameters:

      - result (float)

      - fraction (float)

      - format (str)

    The element contains those children:

      `<text/>` which holds the value of the answer `<tolerance/>` with the relative tolerance for the result in percent `<feedback/>` with general feedback for a true answer.

  hasPicture()

    Create a `Picture` object ``question``if the question needs a pic.

    Return type:

      `bool`

  parse()

    Parse the Question.

    Generates an new Question Element stored as `self.tmpEle:ET.Element` if no Exceptions are raised, `self.tmpEle` is passed to `self.question.element`

    Return type:

      `None`

  setBPoints()

    If there bulletPoints are set in the Spreadsheet it creates an unordered List-Element in `Question.bulletList`.

    Return type:

      `None`

  setMainText()
    Return type:

      `None`

  settings = <excel2moodle.core.settings.Settings object>
  setup(question)
    Return type:

      `None`

    Parameters:

      question (Question)

## excel2moodle.core.question module

class excel2moodle.core.question.ParametricQuestion(*args, **kwargs)

  Bases: `Question`

  mandatoryTags: `ClassVar`[`dict`[`Tags`, `type` | ]] = {Tags.NAME: <class 'str'>, Tags.TEXT: <class 'str'>, Tags.TYPE: <class 'str'>}
  optionalTags: `ClassVar`[`dict`[`Tags`, `type` | ]] = {Tags.PICTURE: int | str}
  standardTags: `ClassVar`[`dict`[`str`, `str` | `float`]] = {'hidden': 0, 'penalty': 0.33333}

class excel2moodle.core.question.Picture(picKey, imgFolder, questionId, width=0)

  Bases: `object`

  Parameters:

    - picKey (str)

    - imgFolder (Path)

    - questionId (str)

    - width (int)

  getImgId(imgKey)

    Get the image ID and width based on the given key.

    The key should either be the full ID (as the question) or only the question Num. If only the number is given, the category.id is prepended. The width should be specified by ID:width:XX. where xx is the px value.

    Return type:

      `bool`

    Parameters:

      imgKey (str)

class excel2moodle.core.question.Question(category, rawData, parent=None)

  Bases: `object`

  Parameters:

    - category (Category)

    - rawData (QuestionData)

  classmethod addStandardTag(key, value)
    Return type:

      `None`

  assemble(variant=0)

    Assemble the question to the valid xml Tree.

    Return type:

      `None`

  mandatoryTags: `ClassVar`[`dict`[`Tags`, `type` | ]] = {Tags.NAME: <class 'str'>, Tags.TEXT: <class 'str'>, Tags.TYPE: <class 'str'>}
  property name: str
  optionalTags: `ClassVar`[`dict`[`Tags`, `type` | ]] = {Tags.PICTURE: int | str}
  property points: float
  property qtype: str
  standardTags: `ClassVar`[`dict`[`str`, `str` | `float`]] = {'hidden': 0, 'penalty': 0.33333}

class excel2moodle.core.question.QuestionData

  Bases: `dict`

  property categoryFallbacks: dict[str, float | str]
  get(key, default=None)

    Get the value for key with correct type.

    If key == Tags.TOLERANCE the tolerance is checked to be a perc. fraction

    Parameters:

      key (Tags)

## excel2moodle.core.validator module

This Module checks if the data inside the Spreadsheet is valid.

Those things are considered:

1. The mandatory entries must not be `Nan`

2. All fields must have the right data-type

If Those checks pass, a question is created, which can be accessed via `Validator.question`

class excel2moodle.core.validator.Validator

  Bases: `object`

  Validate the question data from the spreadsheet.

  Creates a dictionary with the data, for easier access later.

  formatQData()

    Format the dictionary to The types for QuestionData.

    Return type:

      `QuestionData`

  getQuestionData()

    Get the data from the spreadsheet as a dictionary.

    Return type:

      `QuestionData`

  setup(df, index)
    Return type:

      `None`

    Parameters:

      - df (Series)

      - index (int)

  validate()
    Return type:

      `None`

## excel2moodle.ui.settings module

Settings module provides the adjusted subclass of `PySide6.QtCore.QSettings`.

class excel2moodle.core.settings.Settings

  Bases: `object`

  classmethod clear()
    Return type:

      `None`

  classmethod get(key)

    Get the typesafe settings value.

    If no setting is made, the default value is returned.

    Parameters:

      key (Tags)

  classmethod set(key, value)

    Set the setting to value.

    Return type:

      `None`

    Parameters:

      - key (Tags | str)

      - value (float | bool | Path | str)

  values: `ClassVar`[`dict`[`str`, `str` | `float` | `Path`]] = {}

class excel2moodle.core.settings.Tags(_, typ, default, place='project')

  Bases: `StrEnum`

  Tags and Settings Keys are needed to always acess the correct Value.

  The Tags can be used to acess the settings or the QuestionData respectively. As the QSettings settings are accesed via strings, which could easily gotten wrong. Further, this Enum defines, which type a setting has to be.

  ANSPICWIDTH = 'answerimgwidth'
  ANSTYPE = 'answertype'
  BPOINTS = 'bulletpoint'
  CATEGORIESSHEET = 'categoriessheet'
  EQUATION = 'formula'
  FALSE = 'false'
  FIRSTRESULT = 'firstresult'
  IMPORTMODULE = 'importmodule'
  INCLUDEINCATS = 'includeCats'
  LOGFILE = 'logfile'
  LOGLEVEL = 'loglevel'
  NAME = 'name'
  NUMBER = 'number'
  PARTTYPE = 'parttype'
  PICTURE = 'picture'
  PICTUREFOLDER = 'pictureFolder'
  PICTURESUBFOLDER = 'imgfolder'
  PICTUREWIDTH = 'imgwidth'
  POINTS = 'points'
  QUESTIONPART = 'part'
  QUESTIONVARIANT = 'defaultQuestionVariant'
  RESULT = 'result'
  SPREADSHEETPATH = 'spreadsheetFolder'
  TEXT = 'text'
  TOLERANCE = 'tolerance'
  TRUE = 'true'
  TYPE = 'type'
  WRONGSIGNPERCENT = 'wrongsignpercent'
  property default: str | int | float | Path | bool | None

    Get default value for the key.

  property full: str
  property place: str
  typ()

    Get type of the keys data.

    Return type:

      `type`

## excel2moodle.core.stringHelpers module

This Module holds small Helperfunctions related to string manipulation.

excel2moodle.core.stringHelpers.getBase64Img(imgPath)

excel2moodle.core.stringHelpers.getListFromStr(stringList)

  Get a python List of strings from a semi-colon separated string.

  Return type:

    `list`[`str`]

  Parameters:

    stringList (str | list[str])

excel2moodle.core.stringHelpers.getUnitsElementAsString(unit)
  Return type:

    `None`

excel2moodle.core.stringHelpers.printDom(xmlElement, file=None)

  Prints the document tree of `xmlTree` to `file`, if specified, else dumps to stdout.

  Return type:

    `None`

  Parameters:

    - xmlElement (Element)

    - file (Path | None)

excel2moodle.core.stringHelpers.stringToFloat(string)
  Return type:

    `float`

  Parameters:

    string (str)

excel2moodle.core.stringHelpers.texWrapper(text, style)

  Put the strings inside `text` into a LaTex environment.

  if `style == unit`: inside `\\mathrm{}` if `style == math`: inside `\\( \\)`

  Return type:

    `list`[`str`]

  Parameters:

    - text (str | list[str])

    - style (str)