1# Copyright 2004-2008 Roman Yakovenko.
2# Distributed under the Boost Software License, Version 1.0. (See
3# accompanying file LICENSE_1_0.txt or copy at
4# http://www.boost.org/LICENSE_1_0.txt)
5
6import os
7from . import algorithm
8from . import registration_based
9from pygccxml import declarations
10
11class property_t( registration_based.registration_based_t ):
12    def __init__(self, property_def, wrapper=None ):
13        registration_based.registration_based_t.__init__( self )
14        self._property_def = property_def
15        self.works_on_instance = False
16        self._make_function = None
17
18    @property
19    def property_def( self ):
20        return self._property_def
21
22    @property
23    def make_function_identifier( self ):
24        if not self._make_function:
25            self._make_function = algorithm.create_identifier( self, '::boost::python::make_function' )
26        return self._make_function
27
28    def create_function_type_alias_code( self, f, ftype_alias, exported_class_alias=None ):
29        return 'typedef ' + f.function_type().create_typedef( ftype_alias, exported_class_alias ) + ';'
30
31    def create_accessor_code( self, f, ftype_alias ):
32        f_ref_code = '%s( &%s )' % ( ftype_alias, declarations.full_name( f ) )
33        if f.call_policies and f.call_policies.is_default():
34            return f_ref_code
35        result = [ self.make_function_identifier ]
36        result.append( '( ' )
37        result.append( os.linesep )
38        result.append( self.indent( '  ', 2 ) )
39        result.append( f_ref_code )
40        if f.call_policies:
41            result.append( os.linesep )
42            result.append( self.indent( ', ', 2 ) )
43            result.append( f.call_policies.create( self ) )
44        else:
45            result.append( os.linesep )
46            result.append( self.indent( '  ', 2 ) )
47            result.append( '/* undefined call policies */' )
48        result.append( ' ) ' )
49        return ''.join( result )
50
51    def has_long_line( self ):
52        pd = self.property_def
53        if pd.fget.call_policies and not pd.fget.call_policies.is_default():
54            return True
55        elif pd.fset or ( pd.fset and ( pd.fset.call_policies or not pd.fset.call_policies.is_default() ) ):
56            return True
57        elif pd.doc:
58            return True
59        else:
60            return True
61
62    def is_same_parent( self ):
63        pd = self.property_def
64        if not pd.fset:
65            return False
66        return pd.fget.parent is pd.fset.parent
67
68    def create_class_typedef_on_demand( self, f, prefix='' ):
69        if None is f:
70            return ( None, None )
71        if not isinstance( f.parent, declarations.class_t ):
72            return ( None, None )
73        if not declarations.templates.is_instantiation( f.parent.decl_string ):
74            return ( None, None )
75        cls_name = None
76        cls_identifier = algorithm.create_identifier( self, f.parent.decl_string )
77        if prefix:
78            cls_name = prefix + 'class_t'
79        else:
80            cls_name = 'exported_class_t'
81        return ( 'typedef %s %s;' % ( cls_identifier, cls_name ), cls_name )
82
83    def create_property_code( self ):
84        result = []
85        param_sep = ', '
86        if self.has_long_line():
87            param_sep = os.linesep + self.indent( param_sep )
88
89        fget_class_typedef_code, fget_class_alias = None, None
90        fset_class_typedef_code, fset_class_alias = None, None
91        if self.is_same_parent():
92            fget_class_typedef_code, fget_class_alias \
93                = self.create_class_typedef_on_demand( self.property_def.fget )
94            fset_class_alias = fget_class_alias
95            fset_class_typedef_code = fget_class_typedef_code
96        else:
97            fget_class_typedef_code, fget_class_alias \
98                = self.create_class_typedef_on_demand( self.property_def.fget, 'fget_' )
99            fset_class_typedef_code, fset_class_alias \
100                = self.create_class_typedef_on_demand( self.property_def.fset, 'fset_' )
101
102        if fget_class_typedef_code:
103            result.append( fget_class_typedef_code )
104
105        if fset_class_typedef_code and fset_class_typedef_code != fget_class_typedef_code:
106            result.append( os.linesep )
107            result.append( fset_class_typedef_code )
108
109        if result:
110            result.append( 2 * os.linesep )
111
112        result.append( self.create_function_type_alias_code( self.property_def.fget, 'fget', fget_class_alias ) )
113        if self.property_def.fset:
114            result.append( os.linesep )
115            result.append( self.create_function_type_alias_code( self.property_def.fset, 'fset', fset_class_alias ) )
116
117        result.append( 2 * os.linesep )
118
119        add_property = None
120        if self.property_def.is_static:
121            add_property = 'add_static_property'
122        else:
123            add_property = 'add_property'
124
125        class_var_name = self.parent.class_var_name
126        if self.has_long_line():
127            result.append( '%s.%s( ' % ( class_var_name, add_property ) )
128            result.append( os.linesep + self.indent( '"%s"' % self.property_def.name ) )
129        else:
130            result.append( '%s.%s( "%s"' % ( class_var_name, add_property, self.property_def.name ) )
131        result.append( param_sep + self.create_accessor_code( self.property_def.fget, 'fget' ) )
132        if self.property_def.fset:
133            result.append( param_sep + self.create_accessor_code( self.property_def.fset, 'fset' ))
134        if self.property_def.doc:
135            result.append( param_sep + self.property_def.doc)
136        result.append( ' );')
137        return ''.join( result )
138
139    def _create_impl( self ):
140        result = []
141        result.append( '{ //%s' % self.property_def )
142        result.append( '' )
143        result.append( self.indent( self.create_property_code() ) )
144        result.append( '' )
145        result.append( '}' )
146        return os.linesep.join( result )
147
148    def _get_system_files_impl( self ):
149        return []
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171