From d5d002c86a673b23407393de363a4ef530e4bd73 Mon Sep 17 00:00:00 2001 From: Jon-Becker Date: Fri, 12 Apr 2024 10:15:16 -0400 Subject: [PATCH] fix(validation): ensure values, filename, and weights are consistent --- src/common/validate.py | 13 +++++++++ src/core/main.py | 60 ++++++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/common/validate.py b/src/common/validate.py index 87632eb..09b41dd 100644 --- a/src/common/validate.py +++ b/src/common/validate.py @@ -121,6 +121,19 @@ def validate_config(config: dict) -> bool: ) ) + # ensure each layer["values"] has a corresponding layer["filename"] and layer["weights"] + if len(layer["values"]) != len(layer["filename"]) or len( + layer["values"] + ) != len(layer["weights"]): + raise ConfigValidationError( + 'config["layers"][{}]: The number of values, filenames, and weights must be the same. Current values: {}, filenames: {}, weights: {}'.format( + i, + len(layer["values"]), + len(layer["filename"]), + len(layer["weights"]), + ) + ) + # check the incompatibilities and their config values for i, incompatibility in enumerate(config["incompatibilities"]): # check if all required incompatibility keys are present diff --git a/src/core/main.py b/src/core/main.py index a44568b..1999978 100644 --- a/src/core/main.py +++ b/src/core/main.py @@ -20,7 +20,9 @@ def __init__(self, **args): if not args["config"]: raise ValueError("No configuration file was provided.") elif not args["config"].endswith(".json"): - raise ValueError("Invalid configuration file '{}'".format(args["config"])) + raise ValueError( + "Invalid configuration file '{}'".format(args["config"]) + ) if not args["amount"]: raise ValueError("No amount was provided.") @@ -40,7 +42,7 @@ def __init__(self, **args): self.seed = ( int(args["seed"]) if args["seed"] is not None - else int.from_bytes(random.randbytes(16), byteorder='little') + else int.from_bytes(random.randbytes(16), byteorder="little") ) self.start_at = int(args["start_at"]) self.output = args["output"] @@ -124,30 +126,36 @@ def __build_genome_image(self, metadata: dict): Builds the NFT image for a single NFT. """ layers = [] - for index, attr in enumerate(metadata["attributes"]): - # get the image for the trait - for i, trait in enumerate(self.config["layers"][index]["values"]): - if trait == attr["value"]: - layers.append( - Image.open( - f'{self.config["layers"][index]["trait_path"]}/{self.config["layers"][index]["filename"][i]}.png' - ).convert("RGBA") - ) - break - - if len(layers) == 1: - rgb_im = layers[0].convert("RGBA") - elif len(layers) == 2: - main_composite = Image.alpha_composite(layers[0], layers[1]) - rgb_im = main_composite.convert("RGBA") - elif len(layers) >= 3: - main_composite = Image.alpha_composite(layers[0], layers[1]) - for index, remaining in enumerate(layers): - main_composite = Image.alpha_composite(main_composite, remaining) - rgb_im = main_composite.convert("RGBA") - - # create folder structure if it doesn't exist - rgb_im.save("{}/images/{}.png".format(self.output, metadata["token_id"])) + try: + for index, attr in enumerate(metadata["attributes"]): + # get the image for the trait + for i, trait in enumerate(self.config["layers"][index]["values"]): + if trait == attr["value"]: + layers.append( + Image.open( + f'{self.config["layers"][index]["trait_path"]}/{self.config["layers"][index]["filename"][i]}.png' + ).convert("RGBA") + ) + break + + if len(layers) == 1: + rgb_im = layers[0].convert("RGBA") + elif len(layers) == 2: + main_composite = Image.alpha_composite(layers[0], layers[1]) + rgb_im = main_composite.convert("RGBA") + elif len(layers) >= 3: + main_composite = Image.alpha_composite(layers[0], layers[1]) + for index, remaining in enumerate(layers): + main_composite = Image.alpha_composite(main_composite, remaining) + rgb_im = main_composite.convert("RGBA") + + # create folder structure if it doesn't exist + rgb_im.save("{}/images/{}.png".format(self.output, metadata["token_id"])) + + except Exception as e: + self.logger.error( + "Error generating image for token %d: %s", metadata["token_id"], e + ) def generate(self): """