old_contents: """Utility for currying functions."""
  
  from functools import update_wrapper
  from inspect import signature, isclass
  
  
  def get_arg_count(fun):
      """Return the number of parameters a function takes.
  
      Builtins, by default, refer to their class rather than their function call.
      Referring to their __call__ instance allows them to operate as any other
      function when curried.
      """
      if isclass(fun):
          return len(signature(fun.__call__).parameters)
      return len(signature(fun).parameters)
  
  class _CurriedFactory:
      """Return a curried version of the supplied function."""
  
      def __init__(self, fun, args=None, kwargs=None):
          self.fun = fun
          self.arg_count = get_arg_count(fun)
          self.args = args if args is not None else tuple()
          self.kwargs = kwargs if kwargs is not None else dict()
          update_wrapper(self, self.fun)
  
      def __call__(self, *args, **kwargs):
          combined_args = self.args + args
          combined_kwargs = self.kwargs.copy()
          combined_kwargs.update(kwargs)
          if len(combined_args) + len(combined_kwargs) == self.arg_count:
              return self.fun(*combined_args, **combined_kwargs)
          else:
              return _CurriedFactory(
                  self.fun, args=combined_args, kwargs=combined_kwargs
              )
  
  curry = _CurriedFactory
  
new_contents: """Utility for currying functions."""
  
  from functools import update_wrapper
  from inspect import signature, isclass
  
  
  class _CurriedFactory:
      """Return a curried version of the supplied function."""
  
      def __init__(self, fun, args=None, kwargs=None):
          self.fun = fun
  
          self.args = args if args is not None else tuple()
          self.kwargs = kwargs if kwargs is not None else dict()
  
          update_wrapper(self, self.fun)
  
      def __call__(self, *new_args, **new_kwargs):
          next_curried = self.create_next_curried(new_args, new_kwargs)
  
          if next_curried.has_enough_args():
              return next_curried.call_with_arguments()
          else:
              return next_curried
  
      def create_next_curried(self, new_args, new_kwargs):
          next_args = self.args + new_args
  
          next_kwargs = self.kwargs.copy()
          next_kwargs.update(new_kwargs)
  
          return _CurriedFactory(self.fun, args=next_args, kwargs=next_kwargs)
  
      def has_enough_args(self):
          current_arg_count = len(self.args) + len(self.kwargs)
          return current_arg_count == self.get_target_arg_count()
  
      def get_target_arg_count(self):
          callable_ = self.fun
  
          if isclass(callable_):
              # builtins, e.g. `map`, refer to class rather than fn
              callable_ = callable_.__call__
  
          sig = signature(callable_)
          return len(sig.parameters)
  
      def call_with_arguments(self):
          return self.fun(*self.args, **self.kwargs)
  
  curry = _CurriedFactory
  
  
subject: Refactor curry.py