diff --git a/testdata/generate_testdata.py b/testdata/generate_testdata.py index 05379fd..721f64b 100644 --- a/testdata/generate_testdata.py +++ b/testdata/generate_testdata.py @@ -8,6 +8,7 @@ who are friends with each other. import csv import io import json +import mimetypes import os import random import zipfile @@ -15,6 +16,9 @@ from hashlib import sha256 from nacl.signing import SigningKey from nacl.encoding import HexEncoder +IMGS_DIR = os.path.join(os.path.dirname(__file__), 'imgs') +IMAGE_ATTACHMENT_PROBABILITY = 0.9 + # Realistic item database with shared_data category/tag references using fully qualified handles # Format: (name, category_handle, tags_handles, policy, description, qty, properties_list) @@ -250,6 +254,21 @@ def load_shared_data(): return all_tags, all_categories, all_properties +def load_available_images(): + """Read every file in imgs/ and return a list of (data, mime_type) tuples.""" + images = [] + for filename in sorted(os.listdir(IMGS_DIR)): + filepath = os.path.join(IMGS_DIR, filename) + if not os.path.isfile(filepath): + continue + mime_type, _ = mimetypes.guess_type(filename) + if not mime_type: + continue + with open(filepath, 'rb') as f: + images.append((f.read(), mime_type)) + return images + + def generate_keypair(): """Generate a signing key pair and return (hex_private_key, hex_public_key).""" signing_key = SigningKey.generate() @@ -341,7 +360,7 @@ def _quote_value_if_needed(value): return value -def generate_inventory_csv(count, num_locations, location_id_map, item_range=None): +def generate_inventory_csv(count, num_locations, location_id_map, item_range=None, available_images=None): """Generate a realistic inventory.csv with varied items using shared_data references and properties. Args: @@ -349,6 +368,12 @@ def generate_inventory_csv(count, num_locations, location_id_map, item_range=Non num_locations: Number of locations location_id_map: Map of location names to IDs item_range: Tuple of (start_idx, end_idx) to partition the ITEMS_DATABASE, or None for all items + available_images: List of (data, mime_type) tuples to randomly attach to items, or None to skip + + Returns: + Tuple of (inventory_csv_bytes, files) where files maps a zip arcname (matching + `toolshed.offlinedata.inventory_files()`'s 'files/' convention) to file bytes, + for every image actually referenced by an item. """ # Get location names from the map location_names = list(location_id_map.keys()) @@ -365,6 +390,7 @@ def generate_inventory_csv(count, num_locations, location_id_map, item_range=Non selected_items = random.sample(available_items, min(count, len(available_items))) rows = [] + files = {} for i, item_tuple in enumerate(selected_items, 1): # Handle both old format (6 elements) and new format (7 elements with properties) if len(item_tuple) == 7: @@ -382,6 +408,16 @@ def generate_inventory_csv(count, num_locations, location_id_map, item_range=Non properties_str = ', '.join( f"{prop_handle}={_quote_value_if_needed(value)}" for prop_handle, value in properties_list) + # Attach a random image to most items, matching `toolshed.offlinedata.inventory_files()`'s + # 'files/' arcname convention so the import side resolves it as the same file. + files_str = '' + if available_images and random.random() < IMAGE_ATTACHMENT_PROBABILITY: + data, mime_type = random.choice(available_images) + extension = mimetypes.guess_extension(mime_type) or '' + arcname = f'files/{sha256(data).hexdigest()}{extension}' + files[arcname] = data + files_str = arcname + rows.append({ 'id': str(i), 'name': name, @@ -393,7 +429,7 @@ def generate_inventory_csv(count, num_locations, location_id_map, item_range=Non 'storage_location': location, 'tags': ', '.join(tags_for_item), 'properties': properties_str, - 'files': '', + 'files': files_str, 'created_at': '2026-08-01T00:00:00+00:00', }) @@ -403,7 +439,7 @@ def generate_inventory_csv(count, num_locations, location_id_map, item_range=Non writer = csv.DictWriter(output, fieldnames=fieldnames) writer.writeheader() writer.writerows(rows) - return output.getvalue().encode('utf-8') + return output.getvalue().encode('utf-8'), files def generate_sample_files(): @@ -447,9 +483,14 @@ def generate_export_zip(username, domain, friend_username, friend_domain, friend friends_csv = generate_friends_csv(friend_username, friend_domain, friend_public_key) zip_file.writestr('friends.csv', friends_csv) - inventory_csv = generate_inventory_csv(num_items, num_locations, location_id_map, item_range) + available_images = load_available_images() + inventory_csv, item_files = generate_inventory_csv( + num_items, num_locations, location_id_map, item_range, available_images) zip_file.writestr('inventory.csv', inventory_csv) + for arcname, content in item_files.items(): + zip_file.writestr(arcname, content) + sample_files = generate_sample_files() for arcname, content in sample_files.items(): zip_file.writestr(arcname, content) diff --git a/testdata/imgs/1-600x800.png b/testdata/imgs/1-600x800.png new file mode 100644 index 0000000..7f9fabd Binary files /dev/null and b/testdata/imgs/1-600x800.png differ diff --git a/testdata/imgs/1-800x600.png b/testdata/imgs/1-800x600.png new file mode 100644 index 0000000..b16a67b Binary files /dev/null and b/testdata/imgs/1-800x600.png differ diff --git a/testdata/imgs/1.png b/testdata/imgs/1.png new file mode 100644 index 0000000..6973dc1 Binary files /dev/null and b/testdata/imgs/1.png differ diff --git a/testdata/imgs/10-600x800.png b/testdata/imgs/10-600x800.png new file mode 100644 index 0000000..c56d492 Binary files /dev/null and b/testdata/imgs/10-600x800.png differ diff --git a/testdata/imgs/10-800x600.png b/testdata/imgs/10-800x600.png new file mode 100644 index 0000000..c0a99a3 Binary files /dev/null and b/testdata/imgs/10-800x600.png differ diff --git a/testdata/imgs/10.png b/testdata/imgs/10.png new file mode 100644 index 0000000..b22748c Binary files /dev/null and b/testdata/imgs/10.png differ diff --git a/testdata/imgs/2-600x800.png b/testdata/imgs/2-600x800.png new file mode 100644 index 0000000..cc9254b Binary files /dev/null and b/testdata/imgs/2-600x800.png differ diff --git a/testdata/imgs/2-800x600.png b/testdata/imgs/2-800x600.png new file mode 100644 index 0000000..22ae907 Binary files /dev/null and b/testdata/imgs/2-800x600.png differ diff --git a/testdata/imgs/2.png b/testdata/imgs/2.png new file mode 100644 index 0000000..247906b Binary files /dev/null and b/testdata/imgs/2.png differ diff --git a/testdata/imgs/3-600x800.png b/testdata/imgs/3-600x800.png new file mode 100644 index 0000000..6bb4679 Binary files /dev/null and b/testdata/imgs/3-600x800.png differ diff --git a/testdata/imgs/3-800x600.png b/testdata/imgs/3-800x600.png new file mode 100644 index 0000000..b6a4c0c Binary files /dev/null and b/testdata/imgs/3-800x600.png differ diff --git a/testdata/imgs/3.png b/testdata/imgs/3.png new file mode 100644 index 0000000..b1c63eb Binary files /dev/null and b/testdata/imgs/3.png differ diff --git a/testdata/imgs/4-600x800.png b/testdata/imgs/4-600x800.png new file mode 100644 index 0000000..e5092dd Binary files /dev/null and b/testdata/imgs/4-600x800.png differ diff --git a/testdata/imgs/4-800x600.png b/testdata/imgs/4-800x600.png new file mode 100644 index 0000000..a13e6a0 Binary files /dev/null and b/testdata/imgs/4-800x600.png differ diff --git a/testdata/imgs/4.png b/testdata/imgs/4.png new file mode 100644 index 0000000..254b429 Binary files /dev/null and b/testdata/imgs/4.png differ diff --git a/testdata/imgs/5-600x800.png b/testdata/imgs/5-600x800.png new file mode 100644 index 0000000..6a79f21 Binary files /dev/null and b/testdata/imgs/5-600x800.png differ diff --git a/testdata/imgs/5-800x600.png b/testdata/imgs/5-800x600.png new file mode 100644 index 0000000..3c19632 Binary files /dev/null and b/testdata/imgs/5-800x600.png differ diff --git a/testdata/imgs/5.png b/testdata/imgs/5.png new file mode 100644 index 0000000..96c289b Binary files /dev/null and b/testdata/imgs/5.png differ diff --git a/testdata/imgs/6-600x800.png b/testdata/imgs/6-600x800.png new file mode 100644 index 0000000..0097ef0 Binary files /dev/null and b/testdata/imgs/6-600x800.png differ diff --git a/testdata/imgs/6-800x600.png b/testdata/imgs/6-800x600.png new file mode 100644 index 0000000..dfa3d03 Binary files /dev/null and b/testdata/imgs/6-800x600.png differ diff --git a/testdata/imgs/6.png b/testdata/imgs/6.png new file mode 100644 index 0000000..9d5a320 Binary files /dev/null and b/testdata/imgs/6.png differ diff --git a/testdata/imgs/7-600x800.png b/testdata/imgs/7-600x800.png new file mode 100644 index 0000000..10d1355 Binary files /dev/null and b/testdata/imgs/7-600x800.png differ diff --git a/testdata/imgs/7-800x600.png b/testdata/imgs/7-800x600.png new file mode 100644 index 0000000..b96e0e7 Binary files /dev/null and b/testdata/imgs/7-800x600.png differ diff --git a/testdata/imgs/7.png b/testdata/imgs/7.png new file mode 100644 index 0000000..4ab1e72 Binary files /dev/null and b/testdata/imgs/7.png differ diff --git a/testdata/imgs/8-600x800.png b/testdata/imgs/8-600x800.png new file mode 100644 index 0000000..a9efac7 Binary files /dev/null and b/testdata/imgs/8-600x800.png differ diff --git a/testdata/imgs/8-800x600.png b/testdata/imgs/8-800x600.png new file mode 100644 index 0000000..d04f4d5 Binary files /dev/null and b/testdata/imgs/8-800x600.png differ diff --git a/testdata/imgs/8.png b/testdata/imgs/8.png new file mode 100644 index 0000000..06b1771 Binary files /dev/null and b/testdata/imgs/8.png differ diff --git a/testdata/imgs/9-600x800.png b/testdata/imgs/9-600x800.png new file mode 100644 index 0000000..381ed10 Binary files /dev/null and b/testdata/imgs/9-600x800.png differ diff --git a/testdata/imgs/9-800x600.png b/testdata/imgs/9-800x600.png new file mode 100644 index 0000000..5f2a60e Binary files /dev/null and b/testdata/imgs/9-800x600.png differ diff --git a/testdata/imgs/9.png b/testdata/imgs/9.png new file mode 100644 index 0000000..f8fd0be Binary files /dev/null and b/testdata/imgs/9.png differ diff --git a/testdata/user-a.key b/testdata/user-a.key index 3e949af..17abb3c 100644 --- a/testdata/user-a.key +++ b/testdata/user-a.key @@ -1 +1 @@ -795e884532881938a1b03e37731443f4d1974327dafd5d508e0cb00cb0b161b6 \ No newline at end of file +982abc6680c1358c9d4d2436c96c00aebe36e9dd50fe184c12f1ac58fc7f8565 \ No newline at end of file diff --git a/testdata/user-a.zip b/testdata/user-a.zip index 643c04b..e1a7993 100644 Binary files a/testdata/user-a.zip and b/testdata/user-a.zip differ diff --git a/testdata/user-b.key b/testdata/user-b.key index 0c3cf94..3c60be4 100644 --- a/testdata/user-b.key +++ b/testdata/user-b.key @@ -1 +1 @@ -d011fedc3ba733baef6aa7550bbee47db66c2ad3dbfb0f6dcc14c984866df5eb \ No newline at end of file +2e81e04093250c647cb2c364e39017be5aeac0303e138d6ded2e2cc7c3cdcdde \ No newline at end of file diff --git a/testdata/user-b.zip b/testdata/user-b.zip index 1dfe28f..31b027d 100644 Binary files a/testdata/user-b.zip and b/testdata/user-b.zip differ