feat(py): added parsing for Python definitions
What does this MR do?
This MR implements definition extraction for Python. It builds off the analyzer pattern established by the Ruby definitions MR.
Given a Python file, the parser will return a list of DefinitionInfo objects. Each will contain the following:
- The definition type (class, function, or lambda)
 - Name of the function
 - Fully qualified name (FQN) of the definition, with metadata, according to the new schema
 - Match information from the ast-grep rule engine
 - All captured ast-grep variables
 
Notably, there are a few limitations:
- We should compute aliases for each iteration, as described here
- Saving for a future iteration
 
 - Anonymous functions (i.e. unnamed lambdas) are intentionally not handled here because they can't be referenced
 - We do not capture nested lambda definitions (e.g. 
funcs = {"fn_1": lambda x: x}) even though they are technically named- Saving for a future iteration
 
 - Scope changes using 
nonlocalorglobalkeywords are not handled - Dynamic classes are not captured (e.g. 
DynamicClass = type("DynamicClass", (object,), {"method": lambda self: "Hello"})) - Any non-callable definition (e.g. variable assignments, types, etc.) are not captured
 
Related issues
Edited  by Jonathan Shobrook