Я использую .format () для автоматического создания меню. Но мне также нужно отформатировать его, так как пользователи запускают больше тестов, чтобы показать, что эти тесты уже выполнены.
Пример теста dict:
menuDict = {
"1":
{"testDataDict": "testDataDict1",
"testName": "testName1",
"testGroupName":"testGroupName1"},
"2":
{"testDataDict": "testDataDict2",
"testName": "testName2",
"testGroupName":"testGroupName2"
},
"3":
{"testDataDict": "testDataDict3",
"testName": "testName3",
"testGroupName":"testGroupName3"
},
"4":
{"testDataDict": "testDataDict4",
"testName": "testName4",
"testGroupName":"testGroupName3"
}
}
Фактический код:
def menuAutoCreate(menuDict):
testGroupDict = {}
for testNum in menuDict.keys():
try:
testGroupDict[menuDict[testNum]["testGroupName"]].append(testNum)
except:
testGroupDict[menuDict[testNum]["testGroupName"]] = [testNum]
#Groups the tests under the group names
from natsort import natsorted as nt
testGroupNamesList = nt(testGroupDict.keys(), key=lambda y: y.lower())
#Naturally sorts group names so they look orderly
textDump = " "
i = 0
while i < len(testGroupNamesList):
howManyLinesEven = 0
evenList = []
howManyLinesOdd = 0
oddList = []
testGroupNameEven = testGroupNamesList[i]
textDump += "|{:44} |".format(testGroupNameEven)
howManyLinesEven = len(testGroupDict[testGroupNameEven])
evenList = nt(testGroupDict[testGroupNameEven], key=lambda y: y.lower())
#If it's an even number, it puts the menu template on the left side of the screen
if i != len(testGroupNamesList)-1:
testGroupNameOdd = testGroupNamesList[i+1]
textDump += "{:45} |".format(testGroupNameOdd) + "\n"
howManyLinesOdd = len(testGroupDict[testGroupNameOdd])
oddList = nt(testGroupDict[testGroupNameOdd], key=lambda y: y.lower())
#If it's odd, on the right side.
if i == len(testGroupNamesList)-1:
textDump += "{:45} |".format("") + "\n"
#Ensures everything is correctly whitespaced
howManyLines = max(howManyLinesEven, howManyLinesOdd)
#Checks how many lines there are, so if a group has less tests, it will have extra whitespaces
for line in range(howManyLines):
if line < howManyLinesEven:
data = {"testNum": evenList[line], "testName": menuDict[evenList[line]]["testName"]}
textDump += "|({d[testNum]}) {d[testName]:40} {{doneTests[{d[testNum]!r}]:^8}} |".format(d=data)
else:
textDump += "|{:44} |".format("")
if line < howManyLinesOdd:
data = {"testNum": oddList[line], "testName": menuDict[oddList[line]]["testName"]}
textDump += "({d[testNum]}) {d[testName]:41} {{doneTests[{d[testNum]!r}]:^8}} |".format(d=data) + "\n"
else:
textDump += "{:45} |".format("") + "\n"
#Automatically creates a menu
i += 2
print(textDump)
print("\n")
Вывод этого, как и ожидалось:
|testGroupName1 |testGroupName2 |
|(1) testName1 {doneTests['1']:^8} |(2) testName2 {doneTests['2']:^8} |
|testGroupName3 | |
|(3) testName3 {doneTests['3']:^8} | |
|(4) testName4 {doneTests['4']:^8} | | |
Этот последний шаг будет сделан в другом месте, но для демонстрации:
doneTests = {}
for testNum in menuDict.keys():
doneTests[testNum] = "(-)"
print(doneTests)
#textDump.format(**doneTests)
#This doesn't work for some reason?
textDump.format(doneTests = doneTests)
#This step will be repeated as the user does more tests, as an indicator of
which tests are completed.
Ожидаемый результат будет следующим:
|testGroupName1 |testGroupName2 |
|(1) testName1 (-) |(2) testName2 (-) |
|testGroupName3 | |
|(3) testName3 (-) | |
|(4) testName4 (-) | | |
Но здесь выкидывает:
KeyError: "'1'"
Если вы удалите! R из:
{{doneTests[{d[testNum]!r}]:^8}}
бросает
KeyError: 1
вместо этого.
Я попытался отформатировать с помощью! S. Использование списков / кортежей. Добавление и удаление скобок. На данный момент нет идей ...