def test_struct_with_custom_annotations(self): # type: () -> None ns = ApiNamespace('files') annotation_type = AnnotationType('MyAnnotationType', ns, None, [ AnnotationTypeParam('test_param', Int32(), None, False, None, None) ]) ns.add_annotation_type(annotation_type) annotation = CustomAnnotation('MyAnnotation', ns, None, 'MyAnnotationType', None, [], {'test_param': 42}) annotation.set_attributes(annotation_type) ns.add_annotation(annotation) struct = Struct('MyStruct', ns, None) struct.set_attributes(None, [ StructField('annotated_field', Int32(), None, None), StructField('unannotated_field', Int32(), None, None), ]) struct.fields[0].set_annotations([annotation]) result = self._evaluate_struct(ns, struct) expected = textwrap.dedent('''\ class MyStruct(bb.Struct): __slots__ = [ '_annotated_field_value', '_unannotated_field_value', ] _has_required_fields = True def __init__(self, annotated_field=None, unannotated_field=None): self._annotated_field_value = bb.NOT_SET self._unannotated_field_value = bb.NOT_SET if annotated_field is not None: self.annotated_field = annotated_field if unannotated_field is not None: self.unannotated_field = unannotated_field # Instance attribute type: int (validator is set below) annotated_field = bb.Attribute("annotated_field") # Instance attribute type: int (validator is set below) unannotated_field = bb.Attribute("unannotated_field") def _process_custom_annotations(self, annotation_type, field_path, processor): super(MyStruct, self)._process_custom_annotations(annotation_type, field_path, processor) if annotation_type is MyAnnotationType: self.annotated_field = bb.partially_apply(processor, MyAnnotationType(test_param=42))('{}.annotated_field'.format(field_path), self.annotated_field) MyStruct_validator = bv.Struct(MyStruct) ''') # noqa self.maxDiff = None self.assertEqual(result, expected)
def test_route_argument_doc_string(self): backend = PythonClientBackend( target_folder_path='output', args=['-m', 'files', '-c', 'DropboxBase', '-t', 'dropbox']) ns = ApiNamespace('files') self.assertEqual(backend._format_type_in_doc(ns, Int32()), 'int') self.assertEqual(backend._format_type_in_doc(ns, Void()), 'None') self.assertEqual(backend._format_type_in_doc(ns, List(String())), 'List[str]') self.assertEqual(backend._format_type_in_doc(ns, Nullable(String())), 'Nullable[str]') self.assertEqual( backend._format_type_in_doc(ns, Map(String(), Int32())), 'Map[str, int]')
def test_route_with_auth_mode1(self): # type: () -> None route1 = ApiRoute('get_metadata', 1, None) route1.set_attributes(None, ':route:`get_metadata:2`', Void(), Void(), Void(), {'auth': 'app'}) route2 = ApiRoute('get_metadata', 2, None) route2.set_attributes(None, None, Void(), Int32(), Void(), {'auth': 'user, app'}) ns = ApiNamespace('files') ns.add_route(route1) ns.add_route(route2) result = self._evaluate_namespace_with_auth_mode(ns, 'user') expected = textwrap.dedent('''\ # ------------------------------------------ # Routes in files namespace def files_get_metadata_v2(self): arg = None r = self.request( files.get_metadata_v2, 'files', arg, None, ) return r ''') self.assertEqual(result, expected)
def _get_api(self): # type () -> Api api = Api(version='0.1b1') api.route_schema = Struct('Route', 'stone_cfg', None) route1 = ApiRoute('get_metadata', 1, None) route1.set_attributes(None, ':route:`get_metadata`', Void(), Void(), Void(), {}) route2 = ApiRoute('get_metadata', 2, None) route2.set_attributes(None, ':route:`get_metadata:2`', Void(), Int32(), Void(), {}) route3 = ApiRoute('get_metadata', 3, None) route3.set_attributes(None, ':route:`get_metadata:3`', Int32(), Int32(), Void(), {}) ns = ApiNamespace('files') ns.add_route(route1) ns.add_route(route2) ns.add_route(route3) api.namespaces[ns.name] = ns return api, ns
def test_route_with_version_number_conflict(self): # type: () -> None api, ns = self._get_api() # Add a conflicting route route3 = ApiRoute('get_metadata_v2', 1, None) route3.set_attributes(None, None, Void(), Int32(), Void(), {}) ns.add_route(route3) backend = TSDClientBackend(target_folder_path="output", args=['files', 'files']) with self.assertRaises(RuntimeError) as cm: backend._generate_routes(api, 0, 0) self.assertTrue( str(cm.exception).startswith('There is a name conflict between'))
def test_route_with_version_number_name_conflict(self): # type: () -> None route1 = ApiRoute('get_metadata', 2, None) route1.set_attributes(None, None, Void(), Int32(), Void(), {}) route2 = ApiRoute('get_metadata_v2', 1, None) route2.set_attributes(None, None, Void(), Void(), Void(), {}) ns = ApiNamespace('files') ns.add_route(route1) ns.add_route(route2) with self.assertRaises(RuntimeError) as cm: self._evaluate_namespace(ns) self.assertEqual( 'There is a name conflict between {!r} and {!r}'.format( route1, route2), str(cm.exception))
def test_route_with_version_number(self): # type: () -> None route1 = ApiRoute('get_metadata', 1, None) route1.set_attributes(None, ':route:`get_metadata:2`', Void(), Void(), Void(), {}) route2 = ApiRoute('get_metadata', 2, None) route2.set_attributes(None, None, Void(), Int32(), Void(), {}) ns = ApiNamespace('files') ns.add_route(route1) ns.add_route(route2) result = self._evaluate_namespace(ns) expected = textwrap.dedent('''\ def files_get_metadata(self): """ :meth:`files_get_metadata_v2` :rtype: None """ arg = None r = self.request( files.get_metadata, 'files', arg, None, ) return None def files_get_metadata_v2(self): arg = None r = self.request( files.get_metadata_v2, 'files', arg, None, ) return r ''') self.assertEqual(result, expected)
def test_route_with_version_number(self): # type: () -> None route1 = ApiRoute('alpha/get_metadata', 1, None) route1.set_attributes(None, None, Void(), Void(), Void(), {}) route2 = ApiRoute('alpha/get_metadata', 2, None) route2.set_attributes(None, None, Void(), Int32(), Void(), {}) ns = ApiNamespace('files') ns.add_route(route1) ns.add_route(route2) result = self._evaluate_namespace(ns) expected = textwrap.dedent("""\ alpha_get_metadata = bb.Route( 'alpha/get_metadata', 1, False, bv.Void(), bv.Void(), bv.Void(), {}, ) alpha_get_metadata_v2 = bb.Route( 'alpha/get_metadata', 2, False, bv.Void(), bv.Int32(), bv.Void(), {}, ) ROUTES = { 'alpha/get_metadata': alpha_get_metadata, 'alpha/get_metadata:2': alpha_get_metadata_v2, } """) self.assertEqual(result, expected)
def test_check_example(self): # # Test string # s = String(min_length=1, max_length=5) s.check_example( AstExampleField( path='test.stone', lineno=1, lexpos=0, name='v', value='hello', )) with self.assertRaises(InvalidSpec) as cm: s.check_example( AstExampleField( path='test.stone', lineno=1, lexpos=0, name='v', value='', )) self.assertIn("'' has fewer than 1 character(s)", cm.exception.msg) # # Test list # l1 = List(String(min_length=1), min_items=1, max_items=3) l1.check_example( AstExampleField( path='test.stone', lineno=1, lexpos=0, name='v', value=['asd'], )) with self.assertRaises(InvalidSpec) as cm: l1.check_example( AstExampleField( path='test.stone', lineno=1, lexpos=0, name='v', value=[], )) self.assertIn("has fewer than 1 item(s)", cm.exception.msg) # # Test list of lists # l1 = List(List(String(min_length=1), min_items=1)) l1.check_example( AstExampleField( path='test.stone', lineno=1, lexpos=0, name='v', value=[['asd']], )) with self.assertRaises(InvalidSpec) as cm: l1.check_example( AstExampleField( path='test.stone', lineno=1, lexpos=0, name='v', value=[[]], )) self.assertIn("has fewer than 1 item(s)", cm.exception.msg) # # Test Map type # m = Map(String(), String()) # valid example m.check_example( AstExampleField(path='test.stone', lineno=1, lexpos=0, name='v', value={"foo": "bar"})) # does not conform to declared type with self.assertRaises(InvalidSpec): m.check_example( AstExampleField(path='test.stone', lineno=1, lexpos=0, name='v', value={1: "bar"})) with self.assertRaises(ParameterError): # errors because only string types can be used as keys Map(Int32(), String()) s = Struct('S', None, None) s.set_attributes( "Docstring", [ StructField('a', UInt64(), 'a field', None), StructField('b', List(String()), 'a field', None), ], ) s._add_example( AstExample('test.stone', lineno=1, lexpos=0, label='default', text='Default example', fields={ 'a': AstExampleField( path='test.stone', lineno=2, lexpos=0, name='a', value=132, ), 'b': AstExampleField( path='test.stone', lineno=2, lexpos=0, name='b', value=['a'], ), }))
def test_int(self): i = Int32() # check valid Int32 i.check(42) # check number that is too large with self.assertRaises(ValueError) as cm: i.check(2**31) self.assertIn('not within range', cm.exception.args[0]) # check number that is too small with self.assertRaises(ValueError) as cm: i.check(-2**31 - 1) self.assertIn('not within range', cm.exception.args[0]) i = UInt32() # check number that is too large with self.assertRaises(ValueError) as cm: i.check(2**32) self.assertIn('not within range', cm.exception.args[0]) # check number that is too small with self.assertRaises(ValueError) as cm: i.check(-1) self.assertIn('not within range', cm.exception.args[0]) i = Int64() # check number that is too large with self.assertRaises(ValueError) as cm: i.check(2**63) self.assertIn('not within range', cm.exception.args[0]) # check number that is too small with self.assertRaises(ValueError) as cm: i.check(-2**63 - 1) self.assertIn('not within range', cm.exception.args[0]) i = UInt64() # check number that is too large with self.assertRaises(ValueError) as cm: i.check(2**64) self.assertIn('not within range', cm.exception.args[0]) # check number that is too small with self.assertRaises(ValueError) as cm: i.check(-1) self.assertIn('not within range', cm.exception.args[0]) i = Int64(min_value=0, max_value=10) with self.assertRaises(ValueError) as cm: i.check(20) self.assertIn('20 is greater than 10', cm.exception.args[0]) with self.assertRaises(ValueError) as cm: i.check(-5) self.assertIn('-5 is less than 0', cm.exception.args[0]) # check that bad ranges are rejected self.assertRaises(ParameterError, lambda: Int64(min_value=0.1)) self.assertRaises(ParameterError, lambda: Int64(max_value='10'))
def test_annotation_type_class(self): # type: () -> None ns = ApiNamespace('files') annotation_type = AnnotationType('MyAnnotationType', ns, "documented", [ AnnotationTypeParam( 'test_param', Int32(), "test parameter", False, None, None, ), AnnotationTypeParam( 'test_default_param', Int32(), None, True, 5, None, ), ]) result = self._evaluate_annotation_type(ns, annotation_type) expected = textwrap.dedent('''\ class MyAnnotationType(bb.AnnotationType): """ documented :ivar test_param: test parameter """ __slots__ = [ '_test_param', '_test_default_param', ] def __init__(self, test_param=None, test_default_param=5): self._test_param = test_param self._test_default_param = test_default_param @property def test_param(self): """ test parameter :rtype: long """ return self._test_param @property def test_default_param(self): """ :rtype: long """ return self._test_default_param ''') self.assertEqual(result, expected)
def test_struct_with_custom_annotations(self): # type: () -> None ns = ApiNamespace('files') annotation_type = AnnotationType('MyAnnotationType', ns, None, [ AnnotationTypeParam('test_param', Int32(), None, False, None, None) ]) ns.add_annotation_type(annotation_type) annotation = CustomAnnotation('MyAnnotation', ns, None, 'MyAnnotationType', None, [], {'test_param': 42}) annotation.set_attributes(annotation_type) ns.add_annotation(annotation) struct = Struct('MyStruct', ns, None) struct.set_attributes(None, [ StructField('annotated_field', Int32(), None, None), StructField('unannotated_field', Int32(), None, None), ]) struct.fields[0].set_annotations([annotation]) result = self._evaluate_struct(ns, struct) expected = textwrap.dedent('''\ class MyStruct(bb.Struct): __slots__ = [ '_annotated_field_value', '_annotated_field_present', '_unannotated_field_value', '_unannotated_field_present', ] _has_required_fields = True def __init__(self, annotated_field=None, unannotated_field=None): self._annotated_field_value = None self._annotated_field_present = False self._unannotated_field_value = None self._unannotated_field_present = False if annotated_field is not None: self.annotated_field = annotated_field if unannotated_field is not None: self.unannotated_field = unannotated_field @property def annotated_field(self): """ :rtype: long """ if self._annotated_field_present: return self._annotated_field_value else: raise AttributeError("missing required field 'annotated_field'") @annotated_field.setter def annotated_field(self, val): val = self._annotated_field_validator.validate(val) self._annotated_field_value = val self._annotated_field_present = True @annotated_field.deleter def annotated_field(self): self._annotated_field_value = None self._annotated_field_present = False @property def unannotated_field(self): """ :rtype: long """ if self._unannotated_field_present: return self._unannotated_field_value else: raise AttributeError("missing required field 'unannotated_field'") @unannotated_field.setter def unannotated_field(self, val): val = self._unannotated_field_validator.validate(val) self._unannotated_field_value = val self._unannotated_field_present = True @unannotated_field.deleter def unannotated_field(self): self._unannotated_field_value = None self._unannotated_field_present = False def _process_custom_annotations(self, annotation_type, processor): super(MyStruct, self)._process_custom_annotations(annotation_type, processor) if annotation_type is MyAnnotationType: self.annotated_field = bb.partially_apply(processor, MyAnnotationType(test_param=42))(self.annotated_field) def __repr__(self): return 'MyStruct(annotated_field={!r}, unannotated_field={!r})'.format( self._annotated_field_value, self._unannotated_field_value, ) MyStruct_validator = bv.Struct(MyStruct) ''') # noqa self.assertEqual(result, expected)