Фаззер для словарей Python
В настоящее время я ищу фаззер для словарей Python. Я уже знаю о некоторых нечетких инструментах, таких как:
Тем не менее, они кажутся немного шире того, что я ищу. На самом деле моя цель - предоставить словарь Python для данного инструмента и получить новый словарь, очень похожий на входной, но с некоторыми измененными значениями.
Например, предоставление
{k1: "aaa", k2: "bbb", k3: "ccc"}
Я намерен получить следующие новые словари:
{k1: "aaj", k2: "bbb", k3: "ccc"}
{k1: "aaa", k2: "bbr", k3: "ccc"}
{k1: "aaa", k2: "bbb", k3: "ccp"}
...
Вам известны такие инструменты? Любое предложение будет приветствоваться.
В лучшем случае я хотел бы, чтобы это был инструмент с открытым исходным кодом.
РЕДАКТИРОВАТЬ1: я публикую код, который я попробовал до того момента
def change_randomly(self, v):
from random import randint
import string
new_v = list(v)
pos_value = randint(0, len(v)-1)
random_char = string.letters[randint(0, len(string.letters)-1)]
new_v[pos_value] = str(random_char)
return ''.join(new_v)
Конечно, это может быть улучшено, поэтому я с нетерпением жду любой мысли относительно этого.
Спасибо!
1 ответ
Основываясь на комментариях к вопросу, почему бы просто не написать шаблонный фиксатор с фиксированной длиной, подобный этому:
#! /usr/bin/env python
"""Minimal template based dict string value fuzzer."""
from __future__ import print_function
import random
import string
def random_string(rng, length, chars=string.printable):
"""A random string with given length."""
return ''.join(rng.choice(chars) for _ in range(length))
def dict_string_template_fuzz_gen(rng, dict_in):
"""Given a random number generator rng, and starting from
template dict_in expected to have only strings as values,
this generator function yields derived dicts with random
variations in the string values keeping the length of
those identical."""
while True:
yield dict((k, random_string(rng, len(v))) for k, v in dict_in.items())
def main():
"""Drive a test run of minimal template fuzz."""
k1, k2, k3 = 'ka', 'kb', 'kc'
template = {k1: "aaa", k2: "bbb", k3: "ccc"}
print("# Input(template):")
print(template)
rng = random.SystemRandom()
print("# Output(fuzz):")
for n, fuzz in enumerate(dict_string_template_fuzz_gen(rng,
template), start=0):
print(fuzz)
if n > 3:
break
if __name__ == '__main__':
main()
На входе варианта использования это могло бы привести к этому:
# Input(template):
{'kc': 'ccc', 'kb': 'bbb', 'ka': 'aaa'}
# Output(fuzz):
{'kc': '6HZ', 'kb': 'zoD', 'ka': '5>b'}
{'kc': '%<\r', 'kb': 'g>v', 'ka': 'Mo0'}
{'kc': 'Y $', 'kb': '4z.', 'ka': '0".'}
{'kc': '^M.', 'kb': 'QY1', 'ka': 'P0)'}
{'kc': 'FK4', 'kb': 'oZW', 'ka': 'G1q'}
Так что это должно дать OP что-то для запуска, так как это может быть проблемой начальной загрузки, когда знание Python только начинается...
Я просто взломал его - хотя PEP8-совместимый - и он должен работать независимо от того, Python v2 или v3.
Многие открытые концы, над которыми нужно работать..., но стоит попробовать, если библиотеки или некоторого простого расширенного кодирования может быть достаточно. Только ОП будет знать, но может прокомментировать это предложение ответа или обновить вопрос.
Подсказки: я почти всегда использую SystemRandom, чтобы вы могли распараллеливать более надежно. Возможно, есть более быстрые способы, но производительность не была видна мне в спецификации. Оттиски, конечно, растут, потому что это в лучшем случае познавательно. НТН
Обновление: прочитав комментарий OP об изменении только части строк, чтобы сохранить некоторое сходство, можно заменить вышеуказанную функцию фаззера, например:
def dict_string_template_fuzz_len_gen(rng, dict_in, f_len=1):
"""Given a random number generator rng, and starting from
template dict_in expected to have only strings as values,
this generator function yields derived dicts with random
variations in the string values keeping the length of
those identical.
Added as hack the f_len parameter that counts the
characters open to be fuzzed from the end of the string."""
r_s = random_string # shorten for line readability below
while True:
yield dict(
(k, v[:f_len + 1] + r_s(rng, f_len)) for k, v in dict_in.items())
и затем иметь в качестве примера выходных данных:
# Input(template):
{'kc': 'ccc', 'kb': 'bbb', 'ka': 'aaa'}
# Output(fuzz):
{'kc': 'cc\t', 'kb': 'bbd', 'ka': 'aa\\'}
{'kc': 'cc&', 'kb': 'bbt', 'ka': 'aa\\'}
{'kc': 'ccg', 'kb': 'bb_', 'ka': 'aaJ'}
{'kc': 'ccc', 'kb': 'bbv', 'ka': 'aau'}
{'kc': 'ccw', 'kb': 'bbs', 'ka': "aa'"}
При вызове этой функции вместо другой.