Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add create_custom_constraint factory method #836

Closed
amontanez24 opened this issue Jun 6, 2022 · 0 comments · Fixed by #848
Closed

Add create_custom_constraint factory method #836

amontanez24 opened this issue Jun 6, 2022 · 0 comments · Fixed by #848
Labels
feature request Request for a new feature
Milestone

Comments

@amontanez24
Copy link
Contributor

Problem Description

As a user, it would be easier to create my own custom constraints if the only thing I had to supply was the functions for transforming and validating.

Expected behavior

  • Add a factory class method called create_custom_constraint to the constraints module.
  • This method should take in the following parameters:
    • is_valid_fn: required. A function with the following signature is_valid_fn(column_names, data, **kwargs). Must return a series with the rows that are valid for the constraint set to True.
    • transform_fn: optional. A function with the following signature - transform_fn(column_names, data, **kwargs)
    • reverse_transform_fn: optional. A function with the following signature - reverse_transform_fn(column_names, data, **kwargs)
  • The method should return a new constraint class object (not instance) with the is_valid, transform and reverse_transform methods set to what the user provides. The is_valid must be provided, and if either of the two tranform methods are provided, then they both must be.
  • Delete the current CustomConstraint class

Additional context

  • Use the following prototype as inspiration:
def create_custom_constraint(transform_fn=None, reverse_transform_fn=None,
                             is_valid_fn=None):
  
  # User must provide a validity function
  if is_valid_fn is None:
    raise Exception("Missing required parameter 'is_valid'.")
  
  # Transform & reverse are optional but should be provided together or not at all
  if transform_fn is None and reverse_transform_fn is not None:
    raise Exception('No transform is given for the reverse transform.')
  
  if transform_fn is not None and reverse_transform_fn is None:
    raise Exception('No reverse transform is given for the transform.')
  
  # Create a Class that binds to the provided functions
  class CustomConstraint:

    # can keep track of class-level attributes
    TYPE='CUSTOM_CONSTRAINT' # this lets us know how to handle it

    def __init__(self, column_names, **kwargs):
      self.column_names = column_names
      self.kwargs = kwargs
    
    def transform(self, data):
      if transform_fn is None:
        raise Exception('Transform is not defined for this custom constraint.')

      result = transform_fn(self.column_names, data, **self.kwargs)

      if data.shape[0] != result.shape[0]:
        raise Exception('Transformation did not produce the same number of rows as the original')
      return result
    
    def reverse_transform(self, data):
      if reverse_transform_fn is None:
        raise Exception('Reverse transform is not defined for this custom constraint.')

      result = reverse_transform_fn(self.column_names, data, **self.kwargs)
      
      if data.shape[0] != result.shape[0]:
        raise Exception('Reverse transformation did not produce the same number of rows as the original')
      return result
    
    def is_valid(self, data):
      result = is_valid_fn(self.column_names, data, **self.kwargs)
      
      if len(result) != data.shape[0]:
        raise Exception('The validity check should produce exactly 1 True/False value for every row in the data')
      return result

  # return the class to the user 
  return CustomConstraint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Request for a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants