def validate_k_n(k, n): # checks if value fields contained a value _validate_not_empty(k, "K value must be provided.") _validate_not_empty(n, "N value must be provided.") # tries to convert values to numbers if values were numbers try: k = int(k) except ValueError: raise ValidationError(f"Invalid K value. Cannot convert {k} to number") try: n = int(n) except ValueError: raise ValidationError(f"Invalid N value. Cannot convert {n} to number") # k and n must be 1 or greater if k < 1: raise ValidationError( f"Invalid K value. K must be positive, now its value is {k}") if n < 1: raise ValidationError( f"Invalid N value. N must be positive, now its value is {n}") # (k <= n) for standart matrix if (n < k): raise ValidationError( f"Invalid K - ({k}) and N - ({n}) values. For standart matrix, is required that k <= n" ) return k, n
def validate_username(self, key, username): if not username or not username.replace(" ", ""): raise ValidationError("Username is not valid") account = Account.query.filter_by(username=username).one_or_none() if account is not None and account.id != self.id: raise ValidationError("Username already exists") return username
def validate_name(self, key, name): if not name or not name.replace(" ", ""): raise ValidationError("Name is not valid") vendor = Vendor.query.filter_by(name=name).one_or_none() if vendor is not None and vendor.id != self.id: raise ValidationError("Vendor name already exists") return name
def validate_name(self, key, name): if not name or not name.replace(" ", ""): raise ValidationError("Name is not valid") attribute = ProductAttribute.query.filter_by(name=name).one_or_none() if attribute is not None and attribute.id != self.id: raise ValidationError("Name already exists") return name
def validate_name(self, key, name): if not name or not name.replace(" ", ""): raise ValidationError("Campaign name is not valid") campaign = Campaign.query.filter_by(name=name).one_or_none() if campaign is not None: raise ValidationError("Campaign name already exists") return name
def populate_from_decorator(self, decorator_id): """Copy data from the Vendor table, representing the decorator of this variant.""" from src.models import Vendor decorator = Vendor.query.get(decorator_id) if decorator is None: raise ValidationError(f"Vendor {decorator_id} does not exist") if not decorator.is_decorator: raise ValidationError(f"Vendor {decorator_id} is not a decorator") self.decorator_name = decorator.name self.decorator_email = decorator.email self.decorator_address = decorator.address
def load_config(name: str = "settings"): """Load TOML config file and validate it with the associated schema""" # Enforce standard directory structure and a schema for each config file filename = f"{name}.toml" schema = load(join("config", "schemas", filename)) # Allow non-existent files to handle default-valued only schemas file_not_found = None try: config = load(join("config", filename)) except FileNotFoundError as error: config, file_not_found = {}, error validator = Validator(_preprocess_schema_rec(schema, name)) if not validator.validate(config): if file_not_found is not None: raise FileNotFoundError(file_not_found) else: errors = validator.errors raise ValidationError(_format_validation_errors(name, errors)) config_with_empty_sections = _create_empty_sections_rec(schema, config) return validator.normalized(config_with_empty_sections)
def validate_decorations(self, key, value): if isinstance(value, str): value = json.loads(value) if not isinstance(value, list): raise ValidationError("Decorations must be a list") for item in value: if not isinstance(item, dict): raise ValidationError( "Items in decorations list must be dictionaries") if set(item.keys()).difference( {"cost", "location", "logo_description"}): raise ValidationError( f"Invalid keys in decoration: {item.keys()}") return value
def validate_that_matrix_is_standart(matrix: [[int]]): for row_idx, row in enumerate(matrix): for col_idx, value in enumerate(row): if col_idx < len(matrix): if col_idx != row_idx: # checks if not diagonal contains only 0 if value != 0: raise ValidationError( f"Invalid matrix. It is not standart matrix." + f"Value at row {row_idx+1}, column {col_idx+1} must be 0." ) else: # checks if diagonal contains only 1 if value != 1: raise ValidationError( f"Invalid matrix. It is not standart matrix." + f"Value at row {row_idx+1}, column {col_idx+1} must be 1." )
def validate_error_vector(error_vector_str: str, encoded_vector: [int]): # checks if value field contained a value _validate_not_empty( error_vector_str, f"Invalid error vector value. It must must contain at least one character" ) # checks if error vector contains only binary characters if not _vector_consist_of_0_and_1(error_vector_str): raise ValidationError( f"Invalid error vector value - ({error_vector_str}). It must only contain values of 0 and 1" ) # converts error vector string to list of digits error_vector = parser.vector_to_list(error_vector_str) # checks if error vector length is the same as encoded vector length if len(error_vector) != len(encoded_vector): raise ValidationError( f"Invalid error vector value - ({error_vector_str}). It must be same length as encoded vector" ) return error_vector
def validate_product_type(self, key, value): if not value: setattr(self, f"_{key}_empty", True) if (key == "product_type" and getattr(self, "_product_type_id_empty", False)) or ( key == "product_type_id" and getattr(self, "_product_type_empty", False) ): raise ValidationError("Product type not selected") return value
def validate_error_chance(error_chance: str): # checks if value fields contained a value _validate_not_empty( error_chance, "Error chance value must be provided. Value must be between 0 and 1") # tries convert value to number if (error_chance is not float): try: error_chance = float(error_chance) except ValueError: raise ValidationError( f"Invalid error chance value. Cannot convert {error_chance} to number" ) # checks if value os from interval [0,1] if not (0 <= error_chance <= 1): raise ValidationError( f"Invalid error chance value. Value must be between 0 and 1, now its {error_chance}" ) return error_chance
def validate_distributor(self, key, value): if not value: setattr(self, f"_{key}_empty", True) if (key == "distributor" and getattr(self, "_distributor_id_empty", False)) or ( key == "distributor_id" and getattr(self, "_distributor_empty", False) ): raise ValidationError("Distributor not selected") return value
def validate_password(self, key, value): # if nothing was specified, assume the password is to be kept and not changed if value is None: return self._password # password cannot be blank/empty if not value.replace(" ", ""): raise ValidationError("Password can not be empty") return value
def sku(self): if not self.product: raise ValidationError( f"ProductVariant {self.id} is not associated with a product") sku = [str(self.product.item_number)] for attr in self.attribute_values: sku.append(attr.name) return "-".join(sku)
def validate_vector(vector: str): # checks if value fields contained a value _validate_not_empty(vector, "Vector must be provided.") # checks if vector contains only binary characters if not _vector_consist_of_0_and_1(vector): raise ValidationError( f"Invalid vector value - ({vector}). It must only contain values of 0 and 1" ) # converts vector string to list of binary values vector = parser.vector_to_list(vector) return vector
def validate_role(self, key, role, campaign=None, distributor=None): if key == "role_id": from src.models.role import Role self.role = Role.query.get(role) return role # can not run this validator if there is no role if role is None: return if campaign is None: campaign = self.campaign if distributor is None: distributor = self.distributor # raise if there are too many sales execs associated with this distributor. we can only run # this validator if there is a distributor relationship loaded in this model if role.name == "Sales Executive" and distributor: sales_execs = Account.query.filter_by( distributor_id=distributor.id, role_id=role.id ).count() if sales_execs + 1 > distributor.max_sales_count: raise ValidationError( f"You may only create {distributor.max_sales_count} " f"Sales Executive(s) for this distributor" ) # raise if we are putting this user in a campaign that already has a shopper or buyer. we # can only run this validator if a campaign is loaded in this model if role.name in {"Shopper", "Admin Buyer"} and campaign: for account in campaign.accounts: if account.id != self.id and account.role.name == role.name: raise ValidationError( f"Campaign {campaign.id} already has a user with the {role.name} role" ) return role
def total(self): if not self.campaign: raise ValidationError( f"CampaignProductVariant {self.id} is not associated with a campaign" ) if self.ow_cost: ow_cost = self.ow_cost elif not self.campaign.distributor: raise ValidationError( f"Campaign {self.campaign.id} is not associated with a distributor" ) else: ow_cost = self.campaign.distributor.ow_cost total = self.vendor_cost + self.campaign.bfl_cost + ow_cost if self.decorations: total += sum([obj["cost"] for obj in self.decorations]) return total
def validate_attribute_values(self, key, value, product=None): """Validate the values of attributes associated with this variant. Notes ----- A variant should have exactly one attribute value for every attribute specified in its corresponding product type. For example, a wearable product type has color and size attributes. Therefore, a variant of a wearable product must have a size (e.g., XXL) and a color (e.g., hot pink). """ if product is None: product = self.product # skip validation if no product is associated with this model if product is None: return value if not isinstance(value, list): value = [value] # is this value for an attribute associated with this product type? expected_attributes = product.product_type.product_attributes for item in value: if item.product_attribute not in expected_attributes: raise ValidationError( f"Variant of type '{product.product_type.name}' cannot have a " f"'{item.product_attribute.name}' attribute") # has a value for this attribute already been associated with this variant? for attr_value in self.attribute_values: if attr_value.id == item.id: continue if item.product_attribute == attr_value.product_attribute: raise ValidationError( f"Must specify only one value for the " f"'{item.product_attribute.name}' attribute") return value
def delete(self, *args, **kwargs): id = kwargs.get(self.object_id, None) if not id: raise ValidationError("Invalid resource identifier specified") instance = self.SAFRSObject.get_instance(id) if kwargs.get("soft", False): instance.is_deleted = True db.session.add(instance) else: db.session.delete(instance)
def validate_campaign_product_variant(self, key, campaign_product_variant): if key == "campaign_product_variant_id": from src.models.campaign_product_variant import CampaignProductVariant self.campaign_product_variant = CampaignProductVariant.query.get( campaign_product_variant) return campaign_product_variant # if we are changing this line item to another variant, ensure that it has the same # product_id as the previous item. we want to allow switching between variants within a # product--not changing products entirely! if self.campaign_product_variant is not None: if self.campaign_product_variant.product_id != campaign_product_variant.product_id: raise ValidationError( "Can only change to variants of the same product. " "Changing to a different product is currently unsupported." ) if self.campaign_product_variant.campaign_id != campaign_product_variant.campaign_id: raise ValidationError( "The variant you selected was not sold in the campaign associated " "with this order") self.validate_quantity( None, self.quantity, campaign_product_variant=campaign_product_variant) # skip the rest of this validator if order is not set if not self.order: return campaign_product_variant # disallow changes if an order is not processing if self.order.status != "processing": raise ValidationError( "Cannot update an order that is canceled or shipped") return campaign_product_variant
def validate_gen_matrix(matrix: str) -> [[int]]: """validates converts generating matrix string to list of vectors.""" begin_string = "[" end_string = "]" separator = "," # check if the matrix string is in correct format if not (matrix.startswith(begin_string) and matrix.endswith(end_string)): raise ValidationError( f"Invalid matrix value. Matrix {matrix} does not starts with {begin_string} or ends with {end_string}" ) # remove begin and end characters begin_idx = len(begin_string) end_idx = len(matrix) - len(end_string) matrix_str = matrix[begin_idx:end_idx] # matrix splits string into vector strings vectorsStr = matrix_str.split(separator) # validates that matrix contains any vectors if (vectorsStr == []): raise ValidationError( f"Invalid matrix value. Matrix {matrix} does not contain any vectors" ) # validates that all vectors in matrix is the same length if any(map(lambda vector: len(vector) != len(vectorsStr[0]), vectorsStr)): raise ValidationError( f"Invalid matrix value. Not all matrix rows are equal length") try: matrix = [validate_vector(vector) for vector in vectorsStr] except ValidationError as ve: raise ValidationError(f"Invalid matrix vector. {ve.message}", ve) # (k <= n) for standart matrix if (len(matrix) >= len(matrix[0])): raise ValidationError( f"Invalid matrix vector. It must contains more columns than rows (otherwise parity matrix cannot be generated)" ) # checks if matrix is standart validate_that_matrix_is_standart(matrix) return matrix
def sku(self): if self._sku: return self._sku elif not self.product_variant: raise ValidationError( f"CampaignProductVariant {self.id} is not associated with a product variant" ) sku = self.product_variant.sku.split("-") if self.decorations: for decoration in self.decorations: sku.append(decoration["location"].upper()) return "-".join(sku)
def validate_vendor_role(self, key, value): should_raise = False if value is False: if key == "is_supplier" and self.is_decorator is False and self.is_pick_pack is False: should_raise = True elif key == "is_decorator" and self.is_supplier is False and self.is_pick_pack is False: should_raise = True elif key == "is_pick_pack" and self.is_decorator is False and self.is_supplier is False: should_raise = True if should_raise: raise ValidationError( "You must select one of: decorator, supplier, or pick pack") return value
def _format_validation_errors(name, errors): newline = "\n" # Can't use "\n" in f-strings # ! Recursive for arbitrary nesting (use shallow configs to avoid overflow) def format_rec(errors, indent=1): msg = "" for key, values in errors.items(): print(values) # There is always at least one error if type(values[0]) is dict: msg += f"{' ' * indent}- {key}:{newline}" msg += "".join(format_rec(e, indent + 1) for e in values) else: msg += f"{' ' * indent}- {key}: {', '.join(values)}{newline}" return msg msg = format_rec(errors)[:-1] # Remove trailing newline raise ValidationError(f'found in "{name}" config file:{newline}{msg}')
def validate_margin(self, key, margin): if margin > 100: raise ValidationError("Margin cannot be more than 100") return margin
def validate_email(self, key, email): # FIXME: actually validate e-mail addresses if not email or not email.replace(" ", ""): raise ValidationError("E-mail is not valid") return email
def validate_product_types(self, key, value): if not value: raise ValidationError("You must select at least one product type") return value
def _validate_not_empty(value: str, message: str): if value == "": raise ValidationError(message)
def validate_end_date(self, key, end_date): if self.start_date and self.start_date > end_date: raise ValidationError("Start date cannot occur before end date") return end_date