Files
edx-platform/xmodule/modulestore/perf_tests/generate_asset_xml.py
2022-06-20 18:20:06 +05:00

238 lines
5.7 KiB
Python

#!/usr/bin/env python
"""
Generates fake XML for asset metadata.
"""
import random
from datetime import datetime, timedelta
from lxml import etree
from opaque_keys.edx.keys import CourseKey
from xmodule.assetstore import AssetMetadata
try:
import click
except ImportError:
click = None
# Name of the asset metadata XML schema definition file.
ASSET_XSD_FILE = 'assets.xsd'
# Characters used in name generation below.
NAME_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'
NAME_CHARS_W_UNICODE = NAME_CHARS + 'àĚŘDžΦШΩΣӔ'
def coin_flip():
"""
50/50 chance
"""
return random.choice((True, False))
def asset_type():
"""
Pick an asset type at random.
"""
asset_type_choices = (
(95, "asset"),
(100, "video")
)
d100 = random.randint(0, 100)
for choice in asset_type_choices:
if d100 <= choice[0]:
return choice[1]
return asset_type_choices[-1][1]
def filename():
"""
Fake a filename.
"""
fname = ''
for __ in range(random.randint(10, 30)):
fname += random.choice(NAME_CHARS_W_UNICODE)
fname += random.choice(('.jpg', '.pdf', '.png', '.txt'))
return fname
def pathname():
"""
Fake a pathname.
"""
pname = ''
for __ in range(random.randint(2, 3)):
for __ in range(random.randint(5, 10)):
pname += random.choice(NAME_CHARS)
pname += '/'
return pname
def locked():
"""
Locked or unlocked.
"""
return coin_flip()
def fields():
"""
Generate some fake extra fields.
"""
f = {}
if coin_flip():
if coin_flip():
f['copyrighted'] = coin_flip()
if coin_flip():
f['size'] = random.randint(100, 10000000)
if coin_flip():
f['color'] = random.choice(('blue', 'pink', 'fuchsia', 'rose', 'mauve', 'black'))
return f
def user_id():
"""
Fake user id.
"""
return random.randint(1, 100000000)
def versions():
"""
Fake versions.
"""
curr_ver = random.randint(1, 500)
prev_ver = curr_ver - 1
def ver_str(ver):
"""
Version string.
"""
return f'v{ver}.0'
return (ver_str(curr_ver), ver_str(prev_ver))
def date_and_time():
"""
Fake date/time.
"""
start_date = datetime.now()
time_back = timedelta(seconds=random.randint(0, 473040000)) # 15 year interval
return start_date - time_back
def contenttype():
"""
Random MIME type.
"""
return random.choice((
'image/jpeg',
'text/html',
'audio/aiff',
'video/avi',
'text/plain',
'application/msword',
'application/x-gzip',
'application/javascript',
))
def generate_random_asset_md():
"""
Generates a single AssetMetadata object with semi-random data.
"""
course_key = CourseKey.from_string('org/course/run')
asset_key = course_key.make_asset_key(asset_type(), filename())
(curr_version, prev_version) = versions()
return AssetMetadata(
asset_key,
pathname=pathname(),
internal_name=str([filename() for __ in range(10)]),
locked=locked(),
contenttype=contenttype(),
thumbnail=filename(),
fields=fields(),
curr_version=curr_version,
prev_version=prev_version,
edited_by=user_id(),
edited_by_email='staff@edx.org',
edited_on=date_and_time(),
created_by=user_id(),
created_by_email='staff@edx.org',
created_on=date_and_time(),
)
def make_asset_md(amount):
"""
Make a number of fake AssetMetadata objects.
"""
all_asset_md = []
for __ in range(amount):
all_asset_md.append(generate_random_asset_md())
return all_asset_md
def make_asset_xml(amount, xml_filename):
"""
Make an XML file filled with fake AssetMetadata.
"""
all_md = make_asset_md(amount)
xml_root = etree.Element("assets")
for mdata in all_md:
asset_element = etree.SubElement(xml_root, "asset")
mdata.to_xml(asset_element)
with open(xml_filename, "w") as xml_file:
etree.ElementTree(xml_root).write(xml_file)
def validate_xml(xsd_filename, xml_filename):
"""
Validate a generated XML file against the XSD.
"""
with open(xsd_filename) as f:
schema_root = etree.XML(f.read())
schema = etree.XMLSchema(schema_root)
xmlparser = etree.XMLParser(schema=schema)
with open(xml_filename) as f:
etree.fromstring(f.read(), xmlparser)
if click is not None:
@click.command()
@click.option('--num_assets',
type=click.INT,
default=10,
help="Number of assets to be generated by the script.",
required=False
)
@click.option('--output_xml',
type=click.File('w'),
default=AssetMetadata.EXPORTED_ASSET_FILENAME,
help="Filename for the output XML file.",
required=False
)
@click.option('--input_xsd',
type=click.File('r'),
default=ASSET_XSD_FILE,
help="Filename for the XSD (schema) file to read in.",
required=False
)
def cli(num_assets, output_xml, input_xsd):
"""
Generates a number of fake asset metadata items as XML - and validates the XML against the schema.
"""
make_asset_xml(num_assets, output_xml)
# Now - validate the XML against the XSD.
validate_xml(input_xsd, output_xml)
if __name__ == '__main__':
if click is not None:
cli() # pylint: disable=no-value-for-parameter
else:
print("Aborted! Module 'click' is not installed.")