class context_variable(object):

    def __init__(self, func):
        self.func = func
        self.__doc__ = func.__doc__

    def __get__(self, obj, objtype=None):
        # Handle case of being called from class instead of an instance
        if obj is None:
            return self
        # Evaluate the property
        value = self.func(obj)
        # Save value into the instance, replacing the descriptor
        object.__setattr__(obj, self.func.__name__, value)
        return value


def get_context_variables(obj):
    context = {}

    for attr in dir(obj.__class__):
        # Don't bother to check _private/__special attributes
        if attr.startswith('_'):
            continue

        # Get attributes off the class, in case they've already been
        # cached as their final values in the instance dictionary and to
        # avoid general descriptor weirdness
        raw_attr = getattr(obj.__class__, attr)
        if isinstance(raw_attr, context_variable):
            # Force evaluation of obj.`attr`
            context[attr] = getattr(obj, attr)

    return context


class context_variable(object):

    def __init__(self, func):
        self.func = func
        self.__doc__ = func.__doc__

    def __get__(self, obj, objtype=None):
        # Handle case of being called from class instead of an instance
        if obj is None:
            return self
        # If we got a plain value, return that
        if not callable(self.func):
            return self.func
        # Evaluate the property
        value = self.func(obj)
        # Save value into the instance, replacing the descriptor
        object.__setattr__(obj, self.func.__name__, value)
        return value


def get_context_variables(obj):
    context = {}

    for attr in dir(obj.__class__):
        # Don't bother to check _private/__special attributes
        if attr.startswith('_'):
            continue

        # Get attributes off the class, in case they've already been
        # cached as their final values in the instance dictionary and to
        # avoid general descriptor weirdness
        raw_attr = getattr(obj.__class__, attr)
        if isinstance(raw_attr, context_variable):
            # Force evaluation of obj.`attr`
            context[attr] = getattr(obj, attr)

    return context


Allow plain values, not just methods
Allow plain values, not just methods

  class context_variable(object):
  
      def __init__(self, func):
          self.func = func
          self.__doc__ = func.__doc__
  
      def __get__(self, obj, objtype=None):
          # Handle case of being called from class instead of an instance
          if obj is None:
              return self
+         # If we got a plain value, return that
+         if not callable(self.func):
+             return self.func
          # Evaluate the property
          value = self.func(obj)
          # Save value into the instance, replacing the descriptor
          object.__setattr__(obj, self.func.__name__, value)
          return value
  
  
  def get_context_variables(obj):
      context = {}
  
      for attr in dir(obj.__class__):
          # Don't bother to check _private/__special attributes
          if attr.startswith('_'):
              continue
  
          # Get attributes off the class, in case they've already been
          # cached as their final values in the instance dictionary and to
          # avoid general descriptor weirdness
          raw_attr = getattr(obj.__class__, attr)
          if isinstance(raw_attr, context_variable):
              # Force evaluation of obj.`attr`
              context[attr] = getattr(obj, attr)
  
      return context
  
  
Allow plain values, not just methods
## Code Before:
class context_variable(object):

    def __init__(self, func):
        self.func = func
        self.__doc__ = func.__doc__

    def __get__(self, obj, objtype=None):
        # Handle case of being called from class instead of an instance
        if obj is None:
            return self
        # Evaluate the property
        value = self.func(obj)
        # Save value into the instance, replacing the descriptor
        object.__setattr__(obj, self.func.__name__, value)
        return value


def get_context_variables(obj):
    context = {}

    for attr in dir(obj.__class__):
        # Don't bother to check _private/__special attributes
        if attr.startswith('_'):
            continue

        # Get attributes off the class, in case they've already been
        # cached as their final values in the instance dictionary and to
        # avoid general descriptor weirdness
        raw_attr = getattr(obj.__class__, attr)
        if isinstance(raw_attr, context_variable):
            # Force evaluation of obj.`attr`
            context[attr] = getattr(obj, attr)

    return context


## Instruction:
Allow plain values, not just methods
## Code After:
class context_variable(object):

    def __init__(self, func):
        self.func = func
        self.__doc__ = func.__doc__

    def __get__(self, obj, objtype=None):
        # Handle case of being called from class instead of an instance
        if obj is None:
            return self
        # If we got a plain value, return that
        if not callable(self.func):
            return self.func
        # Evaluate the property
        value = self.func(obj)
        # Save value into the instance, replacing the descriptor
        object.__setattr__(obj, self.func.__name__, value)
        return value


def get_context_variables(obj):
    context = {}

    for attr in dir(obj.__class__):
        # Don't bother to check _private/__special attributes
        if attr.startswith('_'):
            continue

        # Get attributes off the class, in case they've already been
        # cached as their final values in the instance dictionary and to
        # avoid general descriptor weirdness
        raw_attr = getattr(obj.__class__, attr)
        if isinstance(raw_attr, context_variable):
            # Force evaluation of obj.`attr`
            context[attr] = getattr(obj, attr)

    return context

