Генерація фіктивних даних з Elizabeth: Частина II

image
Раніше я вже публікував статтю про те, як генерувати фіктивні дані за допомогою Elizabeth — бібліотеки для мови програмування Python. Стаття, яку ви читаєте є продовженням попередньої, тому я не буду приводити основ роботи з бібліотекою. Якщо ви пропустили статтю, полінувалися прочитати або просто не захотіли, то, ймовірно, захочете зараз, бо ця стаття передбачає, що читач вже знайомий з основами бібліотеки. У цій частині статті я буду говорити про те, яким чином організовувати генерацію фіктивних даних у власних програмах, розповім про кількох, на мій погляд, корисних особливості бібліотеки.
Рекомендації
Перш за все хотілося б відзначити, що Elizabeth не розроблялася для використання з конкретною БД або ORM. Основне завдання, яку бібліотека вирішує — це надання валідних даних. Строгих правил роботи з бібліотекою немає, але є рекомендації, які допоможуть тримати ваше тестове оточення в порядку. Рекомендації досить прості і відповідають духу Python.
Структурування
Функції, що виконують генерацію даних і їх запис у БД, необхідно тримати поряд з моделями, а ще краще, як статичні методи моделі до якої вони належать, наприклад методу
_bootstrap()
з попередньої статті. Це потрібно, щоб уникнути біганини по файлах, коли змінюється структура моделі та необхідно додати якесь нове поле.
class Patient(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True)
phone_number = db.Column(db.String(25))
full_name = db.Column(db.String(100))
weight = db.Column(db.String(64))
height = db.Column(db.String(64))
blood_type = db.Column(db.String(64))

def __init__(self, **kwargs):
super(Patient, self).__init__(**kwargs)

@staticmethod
def _bootstrap(count=2000):
from elizabeth import Personal

person = Personal (en)
for _ in range(count):
patient = Patient(email=person.email(),
phone_number=person.telephone(),
full_name=person.full_name(gender='female'),
weight=person.weight(),
height=person.height(),
blood_type=person.blood_type()
)

db.session.add(patient)
try:
db.session.commit()
except Exception:
db.session.rollback()

Створення об'єктів
Якщо ваш додаток очікує дані на одному конкретному мовою і тільки на ньому, то краще всього використовувати клас
Generic
, а не створювати безліч екземплярів класів-постачальників окремо. Використовуючи Generic ви позбудетеся від зайвих рядків коду.
Вірно:
>>> from elizabeth import Generic

>>> generic = Generic('ru')
>>> generic.personal.username()
'sherley3354'
>>> generic.datetime.date()
'14-05-2007'

Невірно:
>>> from elizabeth import Personal, Datetime, Text, Code

>>> personal = Personal('ru')
>>> datetime = Datetime('ru')
>>> text = Text('ru')
>>> code = Code('ru')

У той же час вірно:
>>> from elizabeth import Personal

>>> p_en = Personal (en)
>>> p_sv = Personal('sv')
>>> # ...

Запис даних в БД
Якщо вам потрібно згенерувати дані і записати їх у БД, то рекомендується генерувати дані порціями, а не разом
600k
. Необхідно пам'ятати, що можуть бути якісь обмеження з боку бази даних. Чим менше порції даних, генерирумые для запису, тим швидше запис.
>>> User()._bootstrap(count=2000, locale='de')

Користувальницькі провайдери
Бібліотека підтримує велику кількість даних і в більшості випадків їх буде достатньо, однак для тих, хто хоче створити свої провайдер з більш специфічними даними, така можливість підтримується і робиться це наступним чином:
>>> from elizabeth import Generic

>>> generic = Generic (en)

>>> class SomeProvider():
class Meta:
name = 'some_provider'

def ints(self):
return [i for i in range(1, 5)]

>>> class Another():
def bye(self):
return "Bye!"

>>> generic.add_provider(SomeProvider)
>>> generic.add_provider(Another)

>>> generic.some_provider.ints()
[1, 2, 3, 4]

>>> generic.another.bye()
'Bye!'

Builtin providers

Більшість країн, де той чи інший мова є офіційною, мають дані, які характерні тільки для цих країн. Приміром
CPF
для Бразилії,
SSN
для США. Такого роду дані можуть заподіювати незручності і порушувати порядок (або як мінімум дратувати) тим, що будуть присутні на всіх об'єктах, незалежно від вибраного мовного стандарту. Ви можете самі переконатися в сказаному, якщо подивіться на приклад того, як це виглядало б (код працювати не буде).
>>> from elizabeth import Personal

>>> person = Personal('ru')
>>> person.ssn()
>>> person.cpf()

Думаю багато хто погодиться з тим, що це виглядає зовсім недобре.
Такі дані повинні бути доступні тільки для конкретних мов, тому класи-провайдери, що надають такого роду специфічні дані винесені в окремий подпакет (
elizabeth.builtins
), щоб зберегти загальну для всіх мов структуру класів та об'єктів.
Так це працює:
>>> from elizabeth import Generic
>>> from elizabeth.builtins import Brazil

>>> generic = Generic('pt-br')

>>> class BrazilProvider(Brazil):
class Meta:
name = "brazil_provider"

>>> generic.add_provider(BrazilProvider)
>>> generic.brazil_provider.cpf()
'001.137.297-40'

В яких дані найчастіше виникає необхідність у вашій роботі? Що в бібліотеці втратили і що необхідно негайно додати? Ми були б дуже раді почути ваші побажання/рекомендації/зауваження.
Посилання на проект: тут.
На документацію посилання: тут.
На першу частину статті: тут.
На цьому у мене все, друзі. Вам вдалих тестів і нехай прибуде з вами сила!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.