Counting density of Python code I created a tool to examine Python 3 source code. It measures the density of program. More info in docstring (to not reinvent the wheel). 

What could be done to increase its usability? Any edge cases that I didn't think of?

#!/usr/bin/env python3

'''
Module counts how dense is Python source code in
terms of lexical entities per LoC.
'''

import ast


def traverse(node, line_nos):
    '''
    go through the AST and count lines
    '''
    children = list(ast.iter_child_nodes(node))

    try:
        current_line = node.lineno
    except AttributeError:
        current_line = 0

    count = 1
    line_nos.update([current_line])

    if len(children) == 0:
        return 1

    for child in ast.iter_child_nodes(node):
        count += traverse(child, line_nos)

    return count


def count_code_entities(source):
    '''
    parse the source&amp;count
    '''
    line_nos = set()
    tree = ast.parse(source)

    # len - 1 to compensate for default value 0
    # which cannot hold any code 
    return traverse(tree, line_nos), len(line_nos) - 1


def main():
    '''
    parsin&amp;stuff
    '''
    from argparse import ArgumentParser, FileType
    parser = ArgumentParser()
    parser.add_argument('infile',
                        help='source file to analyze',
                        type=FileType(),
                        default='-',
                        nargs='?',)

    args = parser.parse_args()

    with args.infile as file:
        source = file.read()
        name = file.name

    count, number = count_code_entities(source)
    print(name, ': ', round(count/number, 4), 'entities/line of code')


if __name__ == '__main__':
    main()
The docstrings are vague. Documentation needs to be precise and complete. It should answer questions like "what arguments should I pass?" and "what does it return?" For example, "go through the AST and count lines" should become something like, "Return the number of nodes in the AST rooted at node, and update the set line_nos with the line numbers of these nodes, plus the line number 0 if any node has no line number."
It's not clear that the "plus the line number 0 if any node has no line number" behaviour is needed. Instead of doing this and then having to subtract one later to compensate, why not avoid adding the line number 0 in the first place?
When traversing an AST, it's often convenient to use the ast.NodeVisitor class, like this:

class DensityVisitor(ast.NodeVisitor):
    """AST visitor that accumulates the count of nodes and the set of line
    numbers in the AST.
    """
    def __init__(self):
        self.node_count = 0
        self.line_numbers = set()

    def visit(self, node):
        self.node_count += 1
        try:
            self.line_numbers.add(node.lineno)
        except AttributeError:
            pass
        self.generic_visit(node)

    @property
    def density(self):
        """The density of code (nodes per line) in the visited AST."""
        return self.node_count / len(self.line_numbers)


and then in main you'd write:

visitor = DensityVisitor()
visitor.visit(ast.parse(source))
print('density (nodes/line) =', round(visitor.density, 4)))


Update: Why would you prefer ast.NodeVisitor over explicitly walking the tree using ast.iter_child_nodes plus recursion? Well, because of separation of concerns — the logic for walking the tree is delegated to the ast.NodeVisitor base class, and you only have to specify what happens at each node. (Another possibility would be to use ast.walk.)