@@ -93,15 +93,24 @@ def sanitize_pattern(pattern):
9393 return pattern .replace ('\\ ' , '\\ \\ ' ).replace ('"' , '\\ "' )
9494
9595
96+ _JAVADOC_REPLACEMENT_CHARS = (
97+ ('&' , '&' ),
98+ ('<' , '<' ),
99+ ('>' , '>' ),
100+ )
96101def sanitize_javadoc (doc ):
97102 # sanitize &, <, > characters
98- for char , code in (('&' , '&' ),
99- ('<' , '<' ),
100- ('>' , '>' )):
103+ for char , code in _JAVADOC_REPLACEMENT_CHARS :
101104 doc = doc .replace (char , code )
102105 return doc
103106
104107
108+ def unsanitize_javadoc (doc ):
109+ for char , code in _JAVADOC_REPLACEMENT_CHARS :
110+ doc = doc .replace (code , char )
111+ return doc
112+
113+
105114def oxford_comma_list (values , conjunction = 'and' ):
106115 if not values :
107116 return None
@@ -333,7 +342,9 @@ def current_imports(self):
333342 local_package = self .current_java_package
334343 if local_package :
335344 local_prefix = local_package + '.'
336- return frozenset (i for i in self ._current_imports if not i .startswith (local_prefix ))
345+ def is_local (import_ ):
346+ return import_ .startswith (local_prefix ) and '.' not in import_ [len (local_prefix ):]
347+ return frozenset (i for i in self ._current_imports if not is_local (i ))
337348 else :
338349 return frozenset (self ._current_imports )
339350
@@ -349,13 +360,17 @@ def add_imports(self, *imports):
349360 class if necessary.
350361
351362 """
352- assert self .current_java_class , "No Java class scoped for generation."
363+ assert self ._current_class , "No Java class scoped for generation."
353364
354365 get_name = lambda v : v .rsplit ('.' , 1 )[- 1 ]
355366
356- current_class_prefix = self ._current_class + '.' if self . _current_class else None
367+ current_class_prefix = self ._current_class + '.'
357368
358369 existing_names = set (get_name (import_ ) for import_ in self ._current_imports )
370+
371+ # avoid issues where we import a class with the same name as us
372+ existing_names .add (get_name (self ._current_class ))
373+
359374 for import_ in imports :
360375 if not isinstance (import_ , JavaClass ):
361376 java_class = JavaClass (self , import_ )
@@ -718,8 +733,9 @@ def babel_filenames(self):
718733 # fallback to first route
719734 for route in self .routes :
720735 filenames [route .babel_filename ] = None
736+ # TODO: fallback to aliases. enable assert after doing this
737+ #assert filenames, "namespace not associated with any babel files: %s" % self.babel_name
721738
722- assert filenames , "namespace not associated with any babel files"
723739 return filenames .keys ()
724740
725741 @property
@@ -1561,6 +1577,8 @@ def javadoc_ref_handler(self, tag, val, context=None):
15611577 ref = '{@code %s}' % camelcase (val )
15621578 elif tag == 'link' :
15631579 anchor , link = val .rsplit (' ' , 1 )
1580+ # unsanitize from previous sanitize calls
1581+ anchor = unsanitize_javadoc (anchor )
15641582 # do not sanitize this HTML
15651583 return '<a href="%s">%s</a>' % (link , anchor )
15661584 elif tag == 'val' :
@@ -1574,7 +1592,7 @@ def javadoc_ref_handler(self, tag, val, context=None):
15741592 def translate_babel_doc (self , doc , context = None ):
15751593 if doc :
15761594 handler = lambda tag , val : self .javadoc_ref_handler (tag , val , context = context )
1577- return self ._ctx .g .process_doc (doc , handler )
1595+ return self ._ctx .g .process_doc (sanitize_javadoc ( doc ) , handler )
15781596 else :
15791597 return doc
15801598
@@ -2241,71 +2259,11 @@ def create_package_path(self, package_name):
22412259 def generate_dbx_clients (self ):
22422260 out = self .g .emit
22432261
2244- user_client_class_name = 'DbxClientV2'
2245- with self .dbx_client (
2246- self .ctx .base_package , user_client_class_name , 'user' ,
2247-
2248- """
2249- Use this class to make remote calls to the Dropbox API user endpoints. User endpoints
2250- expose actions you can perform as a Dropbox user. You'll need an access token first,
2251- normally acquired by directing a Dropbox user through the auth flow using {@link
2252- com.dropbox.core.DbxWebAuth}.
2253- """
2254- ):
2255- pass
2256-
2257- with self .dbx_client (
2258- self .ctx .base_package , 'DbxTeamClientV2' , 'team' ,
2259- """
2260- Use this class to make remote calls to the Dropbox API team endpoints. Team endpoints
2261- expose actions you can perform on or for a Dropbox team. You'll need a team access
2262- token first, normally acquired by directing a Dropbox Business team administrator
2263- through the auth flow using {@link com.dropbox.core.DbxWebAuth}.
2264-
2265- Team clients can access user endpoints by using the {@link #asMember} method. This
2266- allows team clients to perform actions as a particular team member.
2267- """
2268- ):
2269- self .doc .generate_javadoc (
2270- """
2271- Returns a {@link %s} that performs requests against Dropbox API user endpoints as the
2272- given team member.
2273-
2274- This method performs no validation of the team member ID.
2275- """ % (user_client_class_name ,),
2276- params = OrderedDict (memberId = "Team member ID of member in this client's team, never {@code null}." ),
2277- returns = "Dropbox client that issues requests to user endpoints as the given team member" ,
2278- throws = OrderedDict (IllegalArgumentException = "If {@code memberId} is {@code null}" )
2279- )
2280-
2281- out ('' )
2282- with self .g .block ('public %s asMember(String memberId)' % (user_client_class_name ,)):
2283- out ('if (memberId == null) throw new IllegalArgumentException("\' memberId\' should not be null");' )
2284- out ('return new %s(new DbxTeamRawClientV2(_client, memberId));' % (user_client_class_name ,))
2285-
2286- self .doc .generate_javadoc (
2287- """
2288- {@link DbxRawClientV2} raw client that adds select-user header to all requests.
2289- Used to perform requests as a particular team member.
2290- """
2291- )
2292- with self .g .block ('private static final class DbxTeamRawClientV2 extends DbxRawClientV2' ):
2293- out ('private final String memberId;' )
2294- out ('' )
2295- with self .g .block ('private DbxTeamRawClientV2(DbxRawClientV2 underlying, String memberId)' ):
2296- out ('super(underlying);' )
2297- out ('this.memberId = memberId;' )
2298- out ('' )
2299- out ('@Override' )
2300- with self .g .block ('protected void addAuthHeaders(java.util.List<HttpRequestor.Header> headers)' ):
2301- out ('super.addAuthHeaders(headers);' )
2302- out ('com.dropbox.core.DbxRequestUtil.addSelectUserHeader(headers, memberId);' )
2303-
2304-
2305- @contextmanager
2306- def dbx_client (self , package_name , class_name , auth , class_doc ):
2307- assert class_doc
2262+ self .generate_dbx_client (self .ctx .base_package , 'DbxClientV2Base' , 'user' )
2263+ self .generate_dbx_client (self .ctx .base_package , 'DbxTeamClientV2Base' , 'team' )
2264+ self .generate_dbx_client (self .ctx .base_package , 'DbxAppClientV2Base' , 'app' )
23082265
2266+ def generate_dbx_client (self , package_name , class_name , auth ):
23092267 out = self .g .emit
23102268
23112269 if auth == 'user' :
@@ -2320,76 +2278,36 @@ def dbx_client(self, package_name, class_name, auth, class_doc):
23202278
23212279 package_relpath = self .create_package_path (package_name )
23222280 file_name = os .path .join (package_relpath , class_name + '.java' )
2323- with self .g .output_to_relative_path (file_name ):
2281+ fq_class_name = package_name + '.' + class_name
2282+ with self .g .output_to_relative_path (file_name ), self .ctx .scoped (fq_class_name ):
23242283 self .generate_file_header ()
23252284 out ('package %s;' % package_name )
2326- out ('' )
2327- out ('import com.dropbox.core.DbxHost;' )
2328- out ('import com.dropbox.core.DbxRequestConfig;' )
2329- out ('import com.dropbox.core.http.HttpRequestor;' )
23302285
23312286 for namespace in namespaces :
2332- out ('import %s;' % namespace .java_class (auth ))
2287+ self .ctx .add_imports (namespace .java_class (auth ))
2288+
2289+ self .importer .generate_imports ()
23332290
23342291 out ('' )
23352292 self .doc .generate_javadoc (
23362293 """
2337- %s
2338-
2339- This class has no mutable state, so it's thread safe as long as you pass in a thread
2340- safe {@link HttpRequestor} implementation.
2341- """ % class_doc
2294+ Base class for %s auth clients.
2295+ """ % auth
23422296 )
2343- with self .g .block ('public final class %s' % class_name ):
2344- out ('private final DbxRawClientV2 _client;' )
2297+ with self .g .block ('public class %s' % class_name ):
2298+ out ('protected final DbxRawClientV2 _client;' )
2299+ out ('' )
23452300 for namespace in namespaces :
23462301 out ('private final %s %s;' % (namespace .java_class (auth ), namespace .java_field ))
2347- out ('' )
2348-
2349- param_docs = OrderedDict ((
2350- ('requestConfig' , 'Default attributes to use for each request' ),
2351- ('accessToken' , 'OAuth 2 access token (that you got from Dropbox) '
2352- 'that gives your app the ability to make Dropbox API calls. Typically '
2353- 'acquired through {@link com.dropbox.core.DbxWebAuth}' ),
2354- ('host' , 'Dropbox hosts to send requests to (used for mocking and testing)' ),
2355- ))
2356-
2357- self .doc .generate_javadoc (
2358- """
2359- Creates a client that uses the given OAuth 2 access token as authorization when
2360- performing requests against the default Dropbox hosts.
2361- """ ,
2362- params = OrderedDict (
2363- (k , v ) for k , v in param_docs .items ()
2364- if k in ('requestConfig' , 'accessToken' )
2365- )
2366- )
2367- with self .g .block ('public %s(DbxRequestConfig requestConfig, String accessToken)' % class_name ):
2368- out ('this(requestConfig, accessToken, DbxHost.DEFAULT);' )
2369-
2370- out ('' )
2371-
2372-
2373- self .doc .generate_javadoc (
2374- """
2375- Same as {@link #%s(DbxRequestConfig, String)} except you can also set the
2376- hostnames of the Dropbox API servers. This is used in testing. You don't
2377- normally need to call this.
2378- """ % (class_name ,),
2379- params = param_docs
2380- )
2381- with self .g .block ('public %s(DbxRequestConfig requestConfig, String accessToken, DbxHost host)' % class_name ):
2382- out ('this(new DbxRawClientV2(requestConfig, accessToken, host));' )
23832302
23842303 out ('' )
23852304 self .doc .generate_javadoc (
23862305 """
23872306 For internal use only.
23882307 """ ,
2389- params = param_docs
2308+ params = (( '_client' , 'Raw v2 client to use for issuing requests' ),)
23902309 )
2391- # package-private
2392- with self .g .block ('%s(DbxRawClientV2 _client)' % class_name ):
2310+ with self .g .block ('protected %s(DbxRawClientV2 _client)' % class_name ):
23932311 out ('this._client = _client;' )
23942312 for namespace in namespaces :
23952313 out ('this.%s = new %s(_client);' % (
@@ -2407,11 +2325,6 @@ def dbx_client(self, package_name, class_name, auth, class_doc):
24072325 with self .g .block ("public %s %s()" % (namespace .java_class (auth ), namespace .java_getter )):
24082326 out ('return %s;' % namespace .java_field )
24092327
2410- out ('' )
2411- # allow caller to add custom methods to the client
2412- yield
2413-
2414-
24152328 def generate_namespace (self , namespace ):
24162329 # create class files for all namespace data types in this package
24172330 for data_type in namespace .data_types :
0 commit comments