docs: def doc(obj, of_class=None):
      """ Get parsed documentation for an object as a dict.
  
      This includes arguments spec, as well as the parsed data from the docstring.
  
      ```python
      from exdoc import doc
      ```
  
      The `doc()` function simply fetches documentation for an object, which can be
  
      * Module
      * Class
      * Function or method
      * Property
  
      The resulting dictionary includes argument specification, as well as parsed docstring:
  
      ```python
      def f(a, b=1, *args):
          ''' Simple function
  
          : param a: First
          : type a: int
          : param b: Second
          : type b: int
          : param args: More numbers
          : returns: nothing interesting
          : rtype: bool
          : raises ValueError: hopeless condition
          '''
  
      from exdoc import doc
  
      doc(f)  # ->
      {
        'module': '__main__',
        'name': 'f',
        'qualname': 'f',  # qualified name: e.g. <class>.<method>
        'signature': 'f(a, b=1, *args)',
        'qsignature': 'f(a, b=1, *args)',  # qualified signature
        'doc': 'Simple function',
        'clsdoc': '',  # doc from the class (used for constructors)
        # Exceptions
        'exc': [
          {'doc': 'hopeless condition', 'name': 'ValueError'}
        ],
        # Return value
        'ret': {'doc': 'nothing interesting', 'type': 'bool'},
        # Arguments
        'args': [
          {'doc': 'First', 'name': 'a', 'type': 'int'},
          {'default': 1, 'doc': 'Second', 'name': 'b', 'type': 'int'},
          {'doc': 'More numbers', 'name': '*args', 'type': None}
        ],
      }
      ```
  
      Note: in Python 3, when documenting a method of a class, pass the class to the `doc()` function as the second argument:
  
      ```python
      doc(cls.method, cls)
      ```
  
      This is necessary because in Python3 methods are not bound like they used to. Now, they are just functions.
  
      :type obj: ModuleType|type|Callable|property
      :param of_class: A class whose method is being documented.
      :type of_class: class|None
      :rtype: Docstring|FDocstring
      """
      # Special care about properties
      if isinstance(obj, property):
          docstr = doc(obj.fget)
          # Some hacks for properties
          docstr.signature = docstr.qsignature= obj.fget.__name__
          docstr.args = docstr.args[1:]
          return docstr
  
      # Module
      module = inspect.getmodule(obj)
      if module:
          module = module.__name__
  
      # Not callable: e.g. modules
      if not callable(obj):
          if hasattr(obj, '__name__'):
              return data.Docstring(qualname=obj.__name__, doc=getdoc(obj))
          else:
              return None
  
      # Callables
      qualname, fun, of_class = _get_callable(obj, of_class)
      docstr = _docspec(fun, module=module, qualname=qualname, of_class=of_class)
  
      # Class? Get doc
      if inspect.isclass(obj):
          # Get class doc
          clsdoc = getdoc(obj)
          # Parse docstring and merge into constructor doc
          if clsdoc:
              # Parse docstring
              clsdoc = _doc_parse(clsdoc, module=module, qualname=qualname)
  
              # Store clsdoc always
              docstr.clsdoc = clsdoc.doc
  
              # Merge exceptions list
              docstr.exc.extend(clsdoc.exc)
  
              # If constructor does not have it's own docstr -- copy it from the clsdoc
              if not docstr.doc:
                  docstr.doc = docstr.clsdoc
  
              # Merge arguments: type, doc
              for a_class in clsdoc.args:
                  for a_constructor in docstr.args:
                      if a_class.name.lstrip('*') == a_constructor.name.lstrip('*'):
                          a_constructor.type = a_class.type
                          a_constructor.doc = a_class.doc
  
      # Finish
      return docstr