Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 421 lines (329 sloc) 16.663 kB
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
1 .. _extension-dev:
2
ee69fb5 @mitsuhiko Added document about extension development
authored
3 Flask Extension Development
4 ===========================
5
6 Flask, being a microframework, often requires some repetitive steps to get
7 a third party library working. Because very often these steps could be
8 abstracted to support multiple projects the `Flask Extension Registry`_
9 was created.
10
11 If you want to create your own Flask extension for something that does not
12 exist yet, this guide to extension development will help you get your
13 extension running in no time and to feel like users would expect your
14 extension to behave.
15
16 .. _Flask Extension Registry: http://flask.pocoo.org/extensions/
17
18 Anatomy of an Extension
19 -----------------------
20
0719ad5 @mitsuhiko Documented new import system for extensions
authored
21 Extensions are all located in a package called ``flask_something``
ee69fb5 @mitsuhiko Added document about extension development
authored
22 where "something" is the name of the library you want to bridge. So for
23 example if you plan to add support for a library named `simplexml` to
0719ad5 @mitsuhiko Documented new import system for extensions
authored
24 Flask, you would name your extension's package ``flask_simplexml``.
ee69fb5 @mitsuhiko Added document about extension development
authored
25
26 The name of the actual extension (the human readable name) however would
27 be something like "Flask-SimpleXML". Make sure to include the name
28 "Flask" somewhere in that name and that you check the capitalization.
29 This is how users can then register dependencies to your extension in
a8f570c @defuz docs: :file:`app.py`, :file:`yourapp/templates`
defuz authored
30 their :file:`setup.py` files.
ee69fb5 @mitsuhiko Added document about extension development
authored
31
0719ad5 @mitsuhiko Documented new import system for extensions
authored
32 Flask sets up a redirect package called :data:`flask.ext` where users
33 should import the extensions from. If you for instance have a package
34 called ``flask_something`` users would import it as
35 ``flask.ext.something``. This is done to transition from the old
36 namespace packages. See :ref:`ext-import-transition` for more details.
ee69fb5 @mitsuhiko Added document about extension development
authored
37
38 But how do extensions look like themselves? An extension has to ensure
39 that it works with multiple Flask application instances at once. This is
40 a requirement because many people will use patterns like the
41 :ref:`app-factories` pattern to create their application as needed to aid
42 unittests and to support multiple configurations. Because of that it is
a3cb2a3 @rduplain Use American English for "behavior" in docs.
rduplain authored
43 crucial that your application supports that kind of behavior.
ee69fb5 @mitsuhiko Added document about extension development
authored
44
a8f570c @defuz docs: :file:`app.py`, :file:`yourapp/templates`
defuz authored
45 Most importantly the extension must be shipped with a :file:`setup.py` file and
ee69fb5 @mitsuhiko Added document about extension development
authored
46 registered on PyPI. Also the development checkout link should work so
47 that people can easily install the development version into their
48 virtualenv without having to download the library by hand.
49
99aaacb @kuyan Emended extensiondev.rst.
kuyan authored
50 Flask extensions must be licensed under a BSD, MIT or more liberal license
51 to be able to be enlisted in the Flask Extension Registry. Keep in mind
52 that the Flask Extension Registry is a moderated place and libraries will
53 be reviewed upfront if they behave as required.
ee69fb5 @mitsuhiko Added document about extension development
authored
54
55 "Hello Flaskext!"
56 -----------------
57
58 So let's get started with creating such a Flask extension. The extension
59 we want to create here will provide very basic support for SQLite3.
60
61 First we create the following folder structure::
62
63 flask-sqlite3/
0719ad5 @mitsuhiko Documented new import system for extensions
authored
64 flask_sqlite3.py
ee69fb5 @mitsuhiko Added document about extension development
authored
65 LICENSE
0719ad5 @mitsuhiko Documented new import system for extensions
authored
66 README
ee69fb5 @mitsuhiko Added document about extension development
authored
67
ff2786d @jgraeme Fix some typos in the docs
jgraeme authored
68 Here's the contents of the most important files:
ee69fb5 @mitsuhiko Added document about extension development
authored
69
70 setup.py
71 ````````
72
a8f570c @defuz docs: :file:`app.py`, :file:`yourapp/templates`
defuz authored
73 The next file that is absolutely required is the :file:`setup.py` file which is
ee69fb5 @mitsuhiko Added document about extension development
authored
74 used to install your Flask extension. The following contents are
75 something you can work with::
76
77 """
78 Flask-SQLite3
79 -------------
80
81 This is the description for that library
82 """
83 from setuptools import setup
84
85
86 setup(
87 name='Flask-SQLite3',
88 version='1.0',
89 url='http://example.com/flask-sqlite3/',
90 license='BSD',
91 author='Your Name',
92 author_email='your-email@example.com',
93 description='Very short description',
94 long_description=__doc__,
0719ad5 @mitsuhiko Documented new import system for extensions
authored
95 py_modules=['flask_sqlite3'],
96 # if you would be using a package instead use packages instead
97 # of py_modules:
98 # packages=['flask_sqlite3'],
ee69fb5 @mitsuhiko Added document about extension development
authored
99 zip_safe=False,
0719ad5 @mitsuhiko Documented new import system for extensions
authored
100 include_package_data=True,
ee69fb5 @mitsuhiko Added document about extension development
authored
101 platforms='any',
102 install_requires=[
103 'Flask'
104 ],
105 classifiers=[
106 'Environment :: Web Environment',
107 'Intended Audience :: Developers',
108 'License :: OSI Approved :: BSD License',
109 'Operating System :: OS Independent',
110 'Programming Language :: Python',
111 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
112 'Topic :: Software Development :: Libraries :: Python Modules'
113 ]
114 )
115
116 That's a lot of code but you can really just copy/paste that from existing
0719ad5 @mitsuhiko Documented new import system for extensions
authored
117 extensions and adapt.
ee69fb5 @mitsuhiko Added document about extension development
authored
118
0719ad5 @mitsuhiko Documented new import system for extensions
authored
119 flask_sqlite3.py
120 ````````````````
ee69fb5 @mitsuhiko Added document about extension development
authored
121
122 Now this is where your extension code goes. But how exactly should such
123 an extension look like? What are the best practices? Continue reading
124 for some insight.
125
126 Initializing Extensions
127 -----------------------
128
129 Many extensions will need some kind of initialization step. For example,
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
130 consider an application that's currently connecting to SQLite like the
131 documentation suggests (:ref:`sqlite3`). So how does the extension
ee69fb5 @mitsuhiko Added document about extension development
authored
132 know the name of the application object?
133
134 Quite simple: you pass it to it.
135
136 There are two recommended ways for an extension to initialize:
137
138 initialization functions:
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
139
ee69fb5 @mitsuhiko Added document about extension development
authored
140 If your extension is called `helloworld` you might have a function
6875a05 @rduplain Fixed small typos in docs. Added a cross-ref.
rduplain authored
141 called ``init_helloworld(app[, extra_args])`` that initializes the
ee69fb5 @mitsuhiko Added document about extension development
authored
142 extension for that application. It could attach before / after
143 handlers etc.
144
145 classes:
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
146
ee69fb5 @mitsuhiko Added document about extension development
authored
147 Classes work mostly like initialization functions but can later be
a3cb2a3 @rduplain Use American English for "behavior" in docs.
rduplain authored
148 used to further change the behavior. For an example look at how the
540eca1 @jgraeme Fix some typos in the docs
jgraeme authored
149 `OAuth extension`_ works: there is an `OAuth` object that provides
ee69fb5 @mitsuhiko Added document about extension development
authored
150 some helper functions like `OAuth.remote_app` to create a reference to
151 a remote application that uses OAuth.
152
153 What to use depends on what you have in mind. For the SQLite 3 extension
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
154 we will use the class-based approach because it will provide users with an
155 object that handles opening and closing database connections.
ee69fb5 @mitsuhiko Added document about extension development
authored
156
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
157 What's important about classes is that they encourage to be shared around
158 on module level. In that case, the object itself must not under any
159 circumstances store any application specific state and must be shareable
160 between different application.
161
ee69fb5 @mitsuhiko Added document about extension development
authored
162 The Extension Code
163 ------------------
164
0719ad5 @mitsuhiko Documented new import system for extensions
authored
165 Here's the contents of the `flask_sqlite3.py` for copy/paste::
ee69fb5 @mitsuhiko Added document about extension development
authored
166
167 import sqlite3
be0b519 @methane Update docs/extensiondev.rst
methane authored
168 from flask import current_app
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
169
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
170 # Find the stack on which we want to store the database connection.
171 # Starting with Flask 0.9, the _app_ctx_stack is the correct one,
172 # before that we need to use the _request_ctx_stack.
173 try:
174 from flask import _app_ctx_stack as stack
175 except ImportError:
176 from flask import _request_ctx_stack as stack
ee69fb5 @mitsuhiko Added document about extension development
authored
177
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
178
ee69fb5 @mitsuhiko Added document about extension development
authored
179 class SQLite3(object):
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
180
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
181 def __init__(self, app=None):
be0b519 @methane Update docs/extensiondev.rst
methane authored
182 self.app = app
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
183 if app is not None:
be0b519 @methane Update docs/extensiondev.rst
methane authored
184 self.init_app(app)
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
185
186 def init_app(self, app):
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
187 app.config.setdefault('SQLITE3_DATABASE', ':memory:')
188 # Use the newstyle teardown_appcontext if it's available,
189 # otherwise fall back to the request context
190 if hasattr(app, 'teardown_appcontext'):
191 app.teardown_appcontext(self.teardown)
192 else:
193 app.teardown_request(self.teardown)
ee69fb5 @mitsuhiko Added document about extension development
authored
194
195 def connect(self):
be0b519 @methane Update docs/extensiondev.rst
methane authored
196 return sqlite3.connect(current_app.config['SQLITE3_DATABASE'])
ee69fb5 @mitsuhiko Added document about extension development
authored
197
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
198 def teardown(self, exception):
199 ctx = stack.top
200 if hasattr(ctx, 'sqlite3_db'):
201 ctx.sqlite3_db.close()
ee69fb5 @mitsuhiko Added document about extension development
authored
202
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
203 @property
204 def connection(self):
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
205 ctx = stack.top
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
206 if ctx is not None:
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
207 if not hasattr(ctx, 'sqlite3_db'):
208 ctx.sqlite3_db = self.connect()
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
209 return ctx.sqlite3_db
210
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
211
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
212 So here's what these lines of code do:
213
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
214 1. The ``__init__`` method takes an optional app object and, if supplied, will
215 call ``init_app``.
216 2. The ``init_app`` method exists so that the ``SQLite3`` object can be
217 instantiated without requiring an app object. This method supports the
218 factory pattern for creating applications. The ``init_app`` will set the
219 configuration for the database, defaulting to an in memory database if
220 no configuration is supplied. In addition, the ``init_app`` method attaches
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
221 the ``teardown`` handler. It will try to use the newstyle app context
222 handler and if it does not exist, falls back to the request context
223 one.
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
224 3. Next, we define a ``connect`` method that opens a database connection.
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
225 4. Finally, we add a ``connection`` property that on first access opens
52f9cef @mitsuhiko More documentation updates for 0.9
authored
226 the database connection and stores it on the context. This is also
227 the recommended way to handling resources: fetch resources lazily the
228 first time they are used.
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
229
230 Note here that we're attaching our database connection to the top
231 application context via ``_app_ctx_stack.top``. Extensions should use
232 the top context for storing their own information with a sufficiently
233 complex name. Note that we're falling back to the
234 ``_request_ctx_stack.top`` if the application is using an older
235 version of Flask that does not support it.
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
236
4aebc26 Hyphenate "class-based"
FND authored
237 So why did we decide on a class-based approach here? Because using our
ee69fb5 @mitsuhiko Added document about extension development
authored
238 extension looks something like this::
239
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
240 from flask import Flask
0719ad5 @mitsuhiko Documented new import system for extensions
authored
241 from flask_sqlite3 import SQLite3
ee69fb5 @mitsuhiko Added document about extension development
authored
242
243 app = Flask(__name__)
244 app.config.from_pyfile('the-config.cfg')
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
245 db = SQLite3(app)
ee69fb5 @mitsuhiko Added document about extension development
authored
246
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
247 You can then use the database from views like this::
ee69fb5 @mitsuhiko Added document about extension development
authored
248
249 @app.route('/')
250 def show_all():
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
251 cur = db.connection.cursor()
ee69fb5 @mitsuhiko Added document about extension development
authored
252 cur.execute(...)
253
32f845e @mitsuhiko Added an example for using the db connection without the request
authored
254 Likewise if you are outside of a request but you are using Flask 0.9 or
255 later with the app context support, you can use the database in the same
256 way::
257
258 with app.app_context():
259 cur = db.connection.cursor()
260 cur.execute(...)
261
663802e @defuz docs: ``with``, ``for``, ``self``
defuz authored
262 At the end of the ``with`` block the teardown handles will be executed
32f845e @mitsuhiko Added an example for using the db connection without the request
authored
263 automatically.
264
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
265 Additionally, the ``init_app`` method is used to support the factory pattern
266 for creating apps::
ee69fb5 @mitsuhiko Added document about extension development
authored
267
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
268 db = Sqlite3()
269 # Then later on.
270 app = create_app('the-config.cfg')
271 db.init_app(app)
ee69fb5 @mitsuhiko Added document about extension development
authored
272
8d1546f @jamesls Reword the docs for writing a flask extension
jamesls authored
273 Keep in mind that supporting this factory pattern for creating apps is required
274 for approved flask extensions (described below).
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
275
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
276 .. admonition:: Note on ``init_app``
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
277
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
278 As you noticed, ``init_app`` does not assign ``app`` to ``self``. This
279 is intentional! Class based Flask extensions must only store the
280 application on the object when the application was passed to the
281 constructor. This tells the extension: I am not interested in using
282 multiple applications.
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
283
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
284 When the extension needs to find the current application and it does
285 not have a reference to it, it must either use the
286 :data:`~flask.current_app` context local or change the API in a way
287 that you can pass the application explicitly.
c1c20ac @mattd Modify extensionsdev documentation.
mattd authored
288
9bed20c @mitsuhiko Added documentation for appcontext and teardown handlers
authored
289
290 Using _app_ctx_stack
291 --------------------
292
293 In the example above, before every request, a ``sqlite3_db`` variable is
294 assigned to ``_app_ctx_stack.top``. In a view function, this variable is
295 accessible using the ``connection`` property of ``SQLite3``. During the
296 teardown of a request, the ``sqlite3_db`` connection is closed. By using
297 this pattern, the *same* connection to the sqlite3 database is accessible
298 to anything that needs it for the duration of the request.
299
300 If the :data:`~flask._app_ctx_stack` does not exist because the user uses
301 an old version of Flask, it is recommended to fall back to
302 :data:`~flask._request_ctx_stack` which is bound to a request.
303
304 Teardown Behavior
305 -----------------
306
307 *This is only relevant if you want to support Flask 0.6 and older*
086ecdb @mitsuhiko Better reraising of exceptions
authored
308
309 Due to the change in Flask 0.7 regarding functions that are run at the end
310 of the request your extension will have to be extra careful there if it
311 wants to continue to support older versions of Flask. The following
312 pattern is a good way to support both::
313
314 def close_connection(response):
315 ctx = _request_ctx_stack.top
316 ctx.sqlite3_db.close()
317 return response
318
319 if hasattr(app, 'teardown_request'):
320 app.teardown_request(close_connection)
321 else:
322 app.after_request(close_connection)
323
324 Strictly speaking the above code is wrong, because teardown functions are
325 passed the exception and typically don't return anything. However because
326 the return value is discarded this will just work assuming that the code
327 in between does not touch the passed parameter.
328
ee69fb5 @mitsuhiko Added document about extension development
authored
329 Learn from Others
330 -----------------
331
332 This documentation only touches the bare minimum for extension
333 development. If you want to learn more, it's a very good idea to check
334 out existing extensions on the `Flask Extension Registry`_. If you feel
335 lost there is still the `mailinglist`_ and the `IRC channel`_ to get some
336 ideas for nice looking APIs. Especially if you do something nobody before
8837678 @mitsuhiko Changed extensiondev docs
authored
337 you did, it might be a very good idea to get some more input. This not
338 only to get an idea about what people might want to have from an
339 extension, but also to avoid having multiple developers working on pretty
340 much the same side by side.
ee69fb5 @mitsuhiko Added document about extension development
authored
341
8837678 @mitsuhiko Changed extensiondev docs
authored
342 Remember: good API design is hard, so introduce your project on the
343 mailinglist, and let other developers give you a helping hand with
344 designing the API.
345
346 The best Flask extensions are extensions that share common idioms for the
347 API. And this can only work if collaboration happens early.
ee69fb5 @mitsuhiko Added document about extension development
authored
348
3adc9de @mitsuhiko Updated docs for extension approval process
authored
349 Approved Extensions
350 -------------------
351
352 Flask also has the concept of approved extensions. Approved extensions
353 are tested as part of Flask itself to ensure extensions do not break on
354 new releases. These approved extensions are listed on the `Flask
355 Extension Registry`_ and marked appropriately. If you want your own
356 extension to be approved you have to follow these guidelines:
357
c1a2e3c @rduplain Add Rule #0 to extension development.
rduplain authored
358 0. An approved Flask extension requires a maintainer. In the event an
359 extension author would like to move beyond the project, the project should
360 find a new maintainer including full source hosting transition and PyPI
361 access. If no maintainer is available, give access to the Flask core team.
3adc9de @mitsuhiko Updated docs for extension approval process
authored
362 1. An approved Flask extension must provide exactly one package or module
0719ad5 @mitsuhiko Documented new import system for extensions
authored
363 named ``flask_extensionname``. They might also reside inside a
364 ``flaskext`` namespace packages though this is discouraged now.
da00160 Fixed some small typos in the documentation.
Sam Anderson authored
365 2. It must ship a testing suite that can either be invoked with ``make test``
366 or ``python setup.py test``. For test suites invoked with ``make
3adc9de @mitsuhiko Updated docs for extension approval process
authored
367 test`` the extension has to ensure that all dependencies for the test
2d237f3 @mattd Fix grammar in extension dev docs.
mattd authored
368 are installed automatically. If tests are invoked with ``python setup.py
a8f570c @defuz docs: :file:`app.py`, :file:`yourapp/templates`
defuz authored
369 test``, test dependencies can be specified in the :file:`setup.py` file. The
2d237f3 @mattd Fix grammar in extension dev docs.
mattd authored
370 test suite also has to be part of the distribution.
3adc9de @mitsuhiko Updated docs for extension approval process
authored
371 3. APIs of approved extensions will be checked for the following
b2fb224 @mitsuhiko Fixed a word in the docs
authored
372 characteristics:
3adc9de @mitsuhiko Updated docs for extension approval process
authored
373
374 - an approved extension has to support multiple applications
375 running in the same Python process.
376 - it must be possible to use the factory pattern for creating
377 applications.
378
a7d83a9 @mitsuhiko Approved extensions must not be GPL
authored
379 4. The license must be BSD/MIT/WTFPL licensed.
3adc9de @mitsuhiko Updated docs for extension approval process
authored
380 5. The naming scheme for official extensions is *Flask-ExtensionName* or
381 *ExtensionName-Flask*.
382 6. Approved extensions must define all their dependencies in the
a8f570c @defuz docs: :file:`app.py`, :file:`yourapp/templates`
defuz authored
383 :file:`setup.py` file unless a dependency cannot be met because it is not
3adc9de @mitsuhiko Updated docs for extension approval process
authored
384 available on PyPI.
66c1395 @mitsuhiko Fixed wording
authored
385 7. The extension must have documentation that uses one of the two Flask
386 themes for Sphinx documentation.
3adc9de @mitsuhiko Updated docs for extension approval process
authored
387 8. The setup.py description (and thus the PyPI description) has to
388 link to the documentation, website (if there is one) and there
389 must be a link to automatically install the development version
390 (``PackageName==dev``).
3da165f @mitsuhiko Fixed typo
authored
391 9. The ``zip_safe`` flag in the setup script must be set to ``False``,
312dfb4 @mitsuhiko Mentioned zip_safe
authored
392 even if the extension would be safe for zipping.
40fad2e @ThomasWaldmann document python 2.6 minimum requirement, remove all stuff that refers…
ThomasWaldmann authored
393 10. An extension currently has to support Python 2.6 as well as
27ce5cc @mitsuhiko Added another rule to the approval list. 2.5-2.7 compatibility
authored
394 Python 2.7
3adc9de @mitsuhiko Updated docs for extension approval process
authored
395
396
0719ad5 @mitsuhiko Documented new import system for extensions
authored
397 .. _ext-import-transition:
398
399 Extension Import Transition
400 ---------------------------
401
402 For a while we recommended using namespace packages for Flask extensions.
403 This turned out to be problematic in practice because many different
404 competing namespace package systems exist and pip would automatically
405 switch between different systems and this caused a lot of problems for
406 users.
407
408 Instead we now recommend naming packages ``flask_foo`` instead of the now
409 deprecated ``flaskext.foo``. Flask 0.8 introduces a redirect import
410 system that lets uses import from ``flask.ext.foo`` and it will try
411 ``flask_foo`` first and if that fails ``flaskext.foo``.
412
413 Flask extensions should urge users to import from ``flask.ext.foo``
414 instead of ``flask_foo`` or ``flaskext_foo`` so that extensions can
415 transition to the new package name without affecting users.
416
417
e89c867 @DasIch Switch packages.python.org to pythonhosted.org
DasIch authored
418 .. _OAuth extension: http://pythonhosted.org/Flask-OAuth/
ee69fb5 @mitsuhiko Added document about extension development
authored
419 .. _mailinglist: http://flask.pocoo.org/mailinglist/
420 .. _IRC channel: http://flask.pocoo.org/community/irc/
Something went wrong with that request. Please try again.