! * Python containers that can be parsed: * * List (a collection which is ordered and changeable, allows duplicate members) * * Tuple (collection which is ordered and unchangeable, allows duplicate members) * * Set (collection which is unordered, unchangeable and unindexed, no duplicate members) * * Numpy's array (with and without the explicit specification of the data type) * */
| 79 | * * Numpy's array (with and without the explicit specification of the data type) |
| 80 | * */ |
| 81 | void VariableParser::parsePythonValues() { |
| 82 | QStringList valueStringList; |
| 83 | QString type = QStringLiteral("float64"); |
| 84 | m_string = m_string.trimmed(); |
| 85 | if (m_string.startsWith(QLatin1String("array"))) { |
| 86 | // parse numpy arrays, string representation like array([1,2,3,4,5]) or |
| 87 | // array([1, 2,3], dtype=uint32) |
| 88 | |
| 89 | // we don't handle array of arrays, e.g. the output of 'np.ones((2,2), dtype=np.int16)' |
| 90 | // which is 'array([[1, 1], [1, 1]], dtype=int16)' |
| 91 | if (m_string.count(QStringLiteral("[")) > 2) |
| 92 | return; |
| 93 | |
| 94 | // the output for columns in panda's dataframes can have line breaks, remove them |
| 95 | m_string = m_string.remove(QLatin1Char('\n')); |
| 96 | |
| 97 | QRegularExpressionMatch match; |
| 98 | auto numpyDatatypeRegex = QStringLiteral("\\s*,\\s*dtype='{0,1}[a-zA-Z0-9\\[\\]]*'{0,1}"); |
| 99 | auto status = m_string.indexOf(QRegularExpression(numpyDatatypeRegex), 0, &match); |
| 100 | if (status >= 0 && match.isValid() && match.captured() != QString()) |
| 101 | type = match.captured().remove(QLatin1Char('\'')).remove(QRegularExpression(QStringLiteral(",\\s*dtype="))); |
| 102 | m_string = m_string.replace(QStringLiteral("array(["), QString()); |
| 103 | m_string = m_string.replace(QRegularExpression(numpyDatatypeRegex), QString()); |
| 104 | m_string = m_string.replace(QStringLiteral("])"), QString()); |
| 105 | } else if (m_string.startsWith(QStringLiteral("["))) { |
| 106 | // parse python's lists |
| 107 | if (m_string.startsWith(QLatin1String("['"))) // python uses ' to quote string values in the output |
| 108 | type = QStringLiteral("text"); |
| 109 | m_string = m_string.replace(QStringLiteral("["), QString()); |
| 110 | m_string = m_string.replace(QStringLiteral("]"), QString()); |
| 111 | } else if (m_string.startsWith(QStringLiteral("("))) { |
| 112 | // parse python's tuples |
| 113 | if (m_string.startsWith(QLatin1String("('"))) |
| 114 | type = QStringLiteral("text"); |
| 115 | m_string = m_string.replace(QStringLiteral("("), QString()); |
| 116 | m_string = m_string.replace(QStringLiteral(")"), QString()); |
| 117 | } else if (m_string.startsWith(QStringLiteral("{"))) { |
| 118 | // parse python's sets |
| 119 | if (m_string.startsWith(QLatin1String("{'"))) |
| 120 | type = QStringLiteral("text"); |
| 121 | m_string = m_string.replace(QStringLiteral("{"), QString()); |
| 122 | m_string = m_string.replace(QStringLiteral("}"), QString()); |
| 123 | } else { |
| 124 | return; |
| 125 | } |
| 126 | |
| 127 | // Fast method to determine the separator. It is assumed if at least one |
| 128 | // commas exist, the comma is the separator |
| 129 | if (m_string.indexOf(QLatin1Char(',')) != -1) |
| 130 | valueStringList = m_string.split(QStringLiteral(",")); |
| 131 | else |
| 132 | valueStringList = m_string.split(QStringLiteral(" ")); |
| 133 | |
| 134 | parseValues(valueStringList, convertNumpyDatatype(type)); |
| 135 | } |
| 136 | |
| 137 | void VariableParser::parseRValues() { |
| 138 | m_string = m_string.trimmed(); |