Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def get_diff(args: argparse.Namespace, stdout: IO, stderr: IO) -> Optional[str]:
args.existing_annotation_strategy = ExistingAnnotationStrategy.REPLICATE
stub = get_stub(args, stdout, stderr)
args.existing_annotation_strategy = ExistingAnnotationStrategy.IGNORE
stub_ignore_anno = get_stub(args, stdout, stderr)
if stub is None or stub_ignore_anno is None:
return None
diff = []
seq1 = (s + "\n" for s in stub.render().split("\n\n\n"))
seq2 = (s + "\n" for s in stub_ignore_anno.render().split("\n\n\n"))
for stub1, stub2 in zip(seq1, seq2):
if stub1 != stub2:
stub_diff = "".join(difflib.ndiff(stub1.splitlines(keepends=True), stub2.splitlines(keepends=True)))
diff.append(stub_diff[:-1])
return "\n\n\n".join(diff)
anything in the module 'foo.bar', while 'foo.bar:Baz' will only generate stubs
for methods attached to the class 'Baz' in module 'foo.bar'. See
https://www.python.org/dev/peps/pep-3155/ for a detailed description of the
qualname format.""")
stub_parser.add_argument(
"--sample-count",
action='store_true',
default=False,
help='Print to stderr the numbers of traces stubs are based on'
)
group = stub_parser.add_mutually_exclusive_group()
group.add_argument(
"--ignore-existing-annotations",
action='store_const',
dest='existing_annotation_strategy',
default=ExistingAnnotationStrategy.REPLICATE,
const=ExistingAnnotationStrategy.IGNORE,
help='Ignore existing annotations and generate stubs only from traces.',
)
group.add_argument(
"--omit-existing-annotations",
action='store_const',
dest='existing_annotation_strategy',
default=ExistingAnnotationStrategy.REPLICATE,
const=ExistingAnnotationStrategy.OMIT,
help='Omit from stub any existing annotations in source. Implied by --apply.',
)
stub_parser.add_argument(
"--diff",
action='store_true',
default=False,
help='Compare stubs generated with and without considering existing annotations.',
def get_updated_definition(
func: Callable,
traces: Iterable[CallTrace],
rewriter: Optional[TypeRewriter] = None,
existing_annotation_strategy: ExistingAnnotationStrategy = ExistingAnnotationStrategy.REPLICATE,
) -> FunctionDefinition:
"""Update the definition for func using the types collected in traces."""
if rewriter is None:
rewriter = NoOpRewriter()
arg_types, return_type, yield_type = shrink_traced_types(traces)
arg_types = {name: rewriter.rewrite(typ) for name, typ in arg_types.items()}
if return_type is not None:
return_type = rewriter.rewrite(return_type)
if yield_type is not None:
yield_type = rewriter.rewrite(yield_type)
return FunctionDefinition.from_callable_and_traced_types(func, arg_types, return_type,
yield_type, existing_annotation_strategy)
def from_callable_and_traced_types(
cls,
func: Callable,
arg_types: Dict[str, type],
return_type: Optional[type],
yield_type: Optional[type],
existing_annotation_strategy: ExistingAnnotationStrategy = ExistingAnnotationStrategy.REPLICATE,
) -> 'FunctionDefinition':
typed_dict_class_stubs: List[ClassStub] = []
new_arg_types = {}
for name, typ in arg_types.items():
if is_anonymous_typed_dict(typ):
class_name = get_typed_dict_class_name(name)
typed_dict_class_stubs.extend(ClassStub.stubs_from_typed_dict(typ, class_name))
typ = make_forward_ref(class_name)
new_arg_types[name] = typ
if return_type and is_anonymous_typed_dict(return_type):
# Replace the dot in a qualified name.
class_name = get_typed_dict_class_name(func.__qualname__.replace('.', '_'))
typed_dict_class_stubs.extend(ClassStub.stubs_from_typed_dict(return_type, class_name))
return_type = make_forward_ref(class_name)
help='Print to stderr the numbers of traces stubs are based on'
)
group = stub_parser.add_mutually_exclusive_group()
group.add_argument(
"--ignore-existing-annotations",
action='store_const',
dest='existing_annotation_strategy',
default=ExistingAnnotationStrategy.REPLICATE,
const=ExistingAnnotationStrategy.IGNORE,
help='Ignore existing annotations and generate stubs only from traces.',
)
group.add_argument(
"--omit-existing-annotations",
action='store_const',
dest='existing_annotation_strategy',
default=ExistingAnnotationStrategy.REPLICATE,
const=ExistingAnnotationStrategy.OMIT,
help='Omit from stub any existing annotations in source. Implied by --apply.',
)
stub_parser.add_argument(
"--diff",
action='store_true',
default=False,
help='Compare stubs generated with and without considering existing annotations.',
)
stub_parser.set_defaults(handler=print_stub_handler)
list_modules_parser = subparsers.add_parser(
'list-modules',
help='Listing of the unique set of module traces',
description='Listing of the unique set of module traces')
list_modules_parser.set_defaults(handler=list_modules_handler)
def update_signature_return(
sig: inspect.Signature,
return_type: type = None,
yield_type: type = None,
existing_annotation_strategy: ExistingAnnotationStrategy = ExistingAnnotationStrategy.REPLICATE,
) -> inspect.Signature:
"""Update return annotation with the supplied types"""
anno = sig.return_annotation
if anno is not inspect.Signature.empty:
# If generating a stub to apply and there's already a return type
# annotation, generate a stub with no return type annotation, to avoid
# the possibility of "incompatible annotation" errors.
if existing_annotation_strategy == ExistingAnnotationStrategy.OMIT:
return sig.replace(return_annotation=inspect.Signature.empty)
# Don't change pre-existing annotations unless asked to
if existing_annotation_strategy == ExistingAnnotationStrategy.REPLICATE:
return sig
# NB: We cannot distinguish between functions that explicitly only
# return None and those that do so implicitly. In the case of generator
# functions both are typed as Iterator[]
if (yield_type is not None) and ((return_type is None) or (return_type == NoneType)):
anno = make_iterator(yield_type)
elif (yield_type is not None) and (return_type is not None):
anno = make_generator(yield_type, NoneType, return_type)
elif return_type is not None:
anno = return_type
return sig.replace(return_annotation=anno)