Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
raise InvalidSpec(
'%s is not a namespace.' % quote(type_ref.ns), *loc)
if type_ref.name not in env:
raise InvalidSpec(
'Symbol %s is undefined.' % quote(type_ref.name), *loc)
obj = env[type_ref.name]
if obj is Void and type_ref.nullable:
raise InvalidSpec('Void cannot be marked nullable.',
*loc)
elif inspect.isclass(obj):
resolved_data_type_args = self._resolve_args(env, type_ref.args)
data_type = self._instantiate_data_type(
obj, resolved_data_type_args, (type_ref.lineno, type_ref.path))
elif isinstance(obj, ApiRoutesByVersion):
raise InvalidSpec('A route cannot be referenced here.',
*loc)
elif type_ref.args[0] or type_ref.args[1]:
# An instance of a type cannot have any additional
# attributes specified.
raise InvalidSpec('Attributes cannot be specified for '
'instantiated type %s.' %
quote(type_ref.name),
*loc)
else:
data_type = env[type_ref.name]
if type_ref.ns:
# Add the source namespace as an import.
namespace = self.api.ensure_namespace(orig_namespace_name)
if isinstance(data_type, UserDefined):
namespace.add_imported_namespace(
def _populate_struct_type_attributes(self, env, data_type):
"""
Converts a forward reference of a struct into a complete definition.
"""
parent_type = None
extends = data_type._ast_node.extends
if extends:
# A parent type must be fully defined and not just a forward
# reference.
parent_type = self._resolve_type(env, extends, True)
if isinstance(parent_type, Alias):
# Restrict extending aliases because it's difficult to generate
# code for it in Python. We put all type references at the end
# to avoid out-of-order declaration issues, but using "extends"
# in Python forces the reference to happen earlier.
raise InvalidSpec(
'A struct cannot extend an alias. '
'Use the canonical name instead.',
data_type._ast_node.lineno, data_type._ast_node.path)
if isinstance(parent_type, Nullable):
raise InvalidSpec(
'A struct cannot extend a nullable type.',
data_type._ast_node.lineno, data_type._ast_node.path)
if not isinstance(parent_type, Struct):
raise InvalidSpec(
'A struct can only extend another struct: '
'%s is not a struct.' % quote(parent_type.name),
data_type._ast_node.lineno, data_type._ast_node.path)
api_type_fields = []
for stone_field in data_type._ast_node.fields:
api_type_field = self._create_struct_field(env, stone_field)
api_type_fields.append(api_type_field)
parent_type = self._resolve_type(env, extends, True)
if isinstance(parent_type, Alias):
# Restrict extending aliases because it's difficult to generate
# code for it in Python. We put all type references at the end
# to avoid out-of-order declaration issues, but using "extends"
# in Python forces the reference to happen earlier.
raise InvalidSpec(
'A struct cannot extend an alias. '
'Use the canonical name instead.',
data_type._ast_node.lineno, data_type._ast_node.path)
if isinstance(parent_type, Nullable):
raise InvalidSpec(
'A struct cannot extend a nullable type.',
data_type._ast_node.lineno, data_type._ast_node.path)
if not isinstance(parent_type, Struct):
raise InvalidSpec(
'A struct can only extend another struct: '
'%s is not a struct.' % quote(parent_type.name),
data_type._ast_node.lineno, data_type._ast_node.path)
api_type_fields = []
for stone_field in data_type._ast_node.fields:
api_type_field = self._create_struct_field(env, stone_field)
api_type_fields.append(api_type_field)
data_type.set_attributes(
data_type._ast_node.doc, api_type_fields, parent_type)
for stone_field in data_type._ast_node.fields:
if stone_field.name == 'other':
raise InvalidSpec(
"Union cannot define an 'other' field because it is "
"reserved as the catch-all field for open unions.",
stone_field.lineno, stone_field.path)
api_type_fields.append(self._create_union_field(env, stone_field))
catch_all_field = None
if data_type.closed:
if parent_type and not parent_type.closed:
# Due to the reversed super type / child type relationship for
# unions, a child type cannot be closed if its parent is open
# because the parent now has an extra field that is not
# recognized by the child if it were substituted in for it.
raise InvalidSpec(
"Union cannot be closed since parent type '%s' is open." % (
parent_type.name),
data_type._ast_node.lineno, data_type._ast_node.path)
else:
if not parent_type or parent_type.closed:
# Create a catch-all field
catch_all_field = UnionField(
name='other', data_type=Void(), doc=None,
ast_node=data_type._ast_node, catch_all=True)
api_type_fields.append(catch_all_field)
data_type.set_attributes(
data_type._ast_node.doc, api_type_fields, parent_type, catch_all_field)
else:
stored_item = self._item_by_canonical_name[base_name]
is_conflict_between_same_type = item.__class__ == stored_item.__class__
# Allow name conflicts between items of the same type when allow_duplicate is True
if not is_conflict_between_same_type or not allow_duplicate:
msg = ("Name of %s '%s' conflicts with name of "
"%s '%s' (%s:%s).") % (
self._get_user_friendly_item_type_as_string(item),
item.name,
self._get_user_friendly_item_type_as_string(stored_item),
stored_item.name,
stored_item.path, stored_item.lineno)
raise InvalidSpec(msg, item.lineno, item.path)
for field in self.fields:
if field.name in self._fields_by_name:
orig_lineno = self._fields_by_name[field.name]._ast_node.lineno
raise InvalidSpec("Field '%s' already defined on line %s." %
(field.name, orig_lineno),
field._ast_node.lineno)
self._fields_by_name[field.name] = field
# Check that the fields for this type do not match any of the fields of
# its parents.
cur_type = self.parent_type
while cur_type:
for field in self.fields:
if field.name in cur_type._fields_by_name:
lineno = cur_type._fields_by_name[field.name]._ast_node.lineno
raise InvalidSpec(
"Field '%s' already defined in parent '%s' on line %d."
% (field.name, cur_type.name, lineno),
field._ast_node.lineno)
cur_type = cur_type.parent_type
# Import namespaces containing any custom annotations
# Note: we don't need to do this for builtin annotations because
# they are treated as globals at the IR level
for field in self.fields:
for annotation in field.custom_annotations:
# first, check the annotation *type*
if annotation.annotation_type.namespace.name != self.namespace.name:
self.namespace.add_imported_namespace(
annotation.annotation_type.namespace,
imported_annotation_type=True)
def _resolve_annotation_type(self, env, annotation_ref):
"""
Resolves the annotation type referenced by annotation_ref.
"""
loc = annotation_ref.lineno, annotation_ref.path
if annotation_ref.ns:
if annotation_ref.ns not in env:
raise InvalidSpec(
'Namespace %s is not imported' % quote(annotation_ref.ns), *loc)
env = env[annotation_ref.ns]
if not isinstance(env, Environment):
raise InvalidSpec(
'%s is not a namespace.' % quote(annotation_ref.ns), *loc)
if annotation_ref.annotation not in env:
raise InvalidSpec(
'Annotation %s does not exist.' % quote(annotation_ref.annotation), *loc)
return env[annotation_ref.annotation]
# arguments are either all kwargs or all args, so don't need to worry about
# providing both positional and keyword argument for same parameter
if param.name in self.kwargs or i < len(self.args):
param_value = self.kwargs[param.name] if self.kwargs else self.args[i]
try:
param.data_type.check(param_value)
except ValueError as e:
raise InvalidSpec('Invalid value for parameter %s of annotation type %s: %s' %
(param.name, self.annotation_type.name, e), self._ast_node.lineno,
self._ast_node.path)
elif isinstance(param.data_type, Nullable):
param_value = None
elif param.has_default:
param_value = param.default
else:
raise InvalidSpec('No value specified for parameter %s of annotation type %s' %
(param.name, self.annotation_type.name), self._ast_node.lineno,
self._ast_node.path)
# now set both kwargs and args to correct value so backend code generators can use
# whichever is more convenient (like if kwargs are not supported in a language)
self.kwargs[param.name] = param_value
if i < len(self.args):
self.args[i] = param_value
else:
self.args.append(param_value)
if new_route_name:
assert new_route_version
is_not_defined = False
is_not_route = False
if new_route_name in env:
if isinstance(env[new_route_name], ApiRoutesByVersion):
if new_route_version not in env[new_route_name].at_version:
is_not_defined = True
else:
is_not_route = True
else:
is_not_defined = True
if is_not_defined:
raise InvalidSpec(
'Undefined route %s at version %d.' % (
quote(new_route_name), new_route_version),
route._ast_node.lineno, route._ast_node.path)
if is_not_route:
raise InvalidSpec(
'%s must be a route.' % quote(new_route_name),
route._ast_node.lineno, route._ast_node.path)
new_route = env[new_route_name].at_version[new_route_version]
deprecated = DeprecationInfo(new_route)
else:
deprecated = DeprecationInfo()
else:
deprecated = None
params = []
for param in item.params:
if param.annotations:
raise InvalidSpec(
'Annotations cannot be applied to parameters of annotation types',
param.lineno, param.path)
param_type = self._resolve_type(env, param.type_ref, True)
dt, nullable_dt = unwrap_nullable(param_type)
if isinstance(dt, Void):
raise InvalidSpec(
'Parameter {} cannot be Void.'.format(quote(param.name)),
param.lineno, param.path)
if nullable_dt and param.has_default:
raise InvalidSpec(
'Parameter {} cannot be a nullable type and have '
'a default specified.'.format(quote(param.name)),
param.lineno, param.path)
if not is_primitive_type(dt):
raise InvalidSpec(
'Parameter {} must have a primitive type (possibly '
'nullable).'.format(quote(param.name)),
param.lineno, param.path)
params.append(AnnotationTypeParam(param.name, param_type, param.doc,
param.has_default, param.default, param))
annotation_type = AnnotationType(item.name, namespace, item.doc, params)
env[item.name] = annotation_type
return annotation_type