def main(): from censiotornado.options import define, options, parse_command_line define("print_headers", type=bool, default=False) define("print_body", type=bool, default=True) define("follow_redirects", type=bool, default=True) define("validate_cert", type=bool, default=True) args = parse_command_line() client = HTTPClient() for arg in args: try: response = client.fetch(arg, follow_redirects=options.follow_redirects, validate_cert=options.validate_cert, ) except HTTPError as e: if e.response is not None: response = e.response else: raise if options.print_headers: print(response.headers) if options.print_body: print(native_str(response.body)) client.close()
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging import censiotornado.escape import censiotornado.ioloop import censiotornado.web import os.path import uuid from censiotornado.concurrent import Future from censiotornado import gen from censiotornado.options import define, options, parse_command_line define("port", default=8888, help="run on the given port", type=int) define("debug", default=False, help="run in debug mode") class MessageBuffer(object): def __init__(self): self.waiters = set() self.cache = [] self.cache_size = 200 def wait_for_messages(self, cursor=None): # Construct a Future to return to our caller. This allows # wait_for_messages to be yielded from a coroutine even though # it is not a coroutine itself. We will set the result of the # Future when results are available. result_future = Future()
#!/usr/bin/env python # # Downloads a large file in chunked encoding with both curl and simple clients import logging from censiotornado.curl_httpclient import CurlAsyncHTTPClient from censiotornado.simple_httpclient import SimpleAsyncHTTPClient from censiotornado.ioloop import IOLoop from censiotornado.options import define, options, parse_command_line from censiotornado.web import RequestHandler, Application define('port', default=8888) define('num_chunks', default=1000) define('chunk_size', default=2048) class ChunkHandler(RequestHandler): def get(self): for i in xrange(options.num_chunks): self.write('A' * options.chunk_size) self.flush() self.finish() def main(): parse_command_line() app = Application([('/', ChunkHandler)]) app.listen(options.port, address='127.0.0.1') def callback(response): response.rethrow()
import markdown import os.path import re import subprocess import torndb import censiotornado.escape from censiotornado import gen import censiotornado.httpserver import censiotornado.ioloop import censiotornado.options import censiotornado.web import unicodedata from censiotornado.options import define, options define("port", default=8888, help="run on the given port", type=int) define("mysql_host", default="127.0.0.1:3306", help="blog database host") define("mysql_database", default="blog", help="blog database name") define("mysql_user", default="blog", help="blog database user") define("mysql_password", default="blog", help="blog database password") # A thread pool to be used for password hashing with bcrypt. executor = concurrent.futures.ThreadPoolExecutor(2) class Application(censiotornado.web.Application): def __init__(self): handlers = [ (r"/", HomeHandler), (r"/archive", ArchiveHandler), (r"/feed", FeedHandler),
def main(**kwargs): """A simple test runner. This test runner is essentially equivalent to `unittest.main` from the standard library, but adds support for tornado-style option parsing and log formatting. The easiest way to run a test is via the command line:: python -m tornado.testing tornado.test.stack_context_test See the standard library unittest module for ways in which tests can be specified. Projects with many tests may wish to define a test script like ``tornado/test/runtests.py``. This script should define a method ``all()`` which returns a test suite and then call `tornado.testing.main()`. Note that even when a test script is used, the ``all()`` test suite may be overridden by naming a single test on the command line:: # Runs all tests python -m tornado.test.runtests # Runs one test python -m tornado.test.runtests tornado.test.stack_context_test Additional keyword arguments passed through to ``unittest.main()``. For example, use ``tornado.testing.main(verbosity=2)`` to show many test details as they are run. See http://docs.python.org/library/unittest.html#unittest.main for full argument list. """ from censiotornado.options import define, options, parse_command_line define('exception_on_interrupt', type=bool, default=True, help=("If true (default), ctrl-c raises a KeyboardInterrupt " "exception. This prints a stack trace but cannot interrupt " "certain operations. If false, the process is more reliably " "killed, but does not print a stack trace.")) # support the same options as unittest's command-line interface define('verbose', type=bool) define('quiet', type=bool) define('failfast', type=bool) define('catch', type=bool) define('buffer', type=bool) argv = [sys.argv[0]] + parse_command_line(sys.argv) if not options.exception_on_interrupt: signal.signal(signal.SIGINT, signal.SIG_DFL) if options.verbose is not None: kwargs['verbosity'] = 2 if options.quiet is not None: kwargs['verbosity'] = 0 if options.failfast is not None: kwargs['failfast'] = True if options.catch is not None: kwargs['catchbreak'] = True if options.buffer is not None: kwargs['buffer'] = True if __name__ == '__main__' and len(argv) == 1: print("No tests specified", file=sys.stderr) sys.exit(1) try: # In order to be able to run tests by their fully-qualified name # on the command line without importing all tests here, # module must be set to None. Python 3.2's unittest.main ignores # defaultTest if no module is given (it tries to do its own # test discovery, which is incompatible with auto2to3), so don't # set module if we're not asking for a specific test. if len(argv) > 1: unittest.main(module=None, argv=argv, **kwargs) else: unittest.main(defaultTest="all", argv=argv, **kwargs) except SystemExit as e: if e.code == 0: gen_log.info('PASS') else: gen_log.error('FAIL') raise
(you could also generate a random value for "cookie_secret" and put it in the same file, although it's not necessary to run this demo) 3) Run this program and go to http://localhost:8888 (by default) in your browser. """ import logging from censiotornado.auth import TwitterMixin from censiotornado.escape import json_decode, json_encode from censiotornado.ioloop import IOLoop from censiotornado import gen from censiotornado.options import define, options, parse_command_line, parse_config_file from censiotornado.web import Application, RequestHandler, authenticated define('port', default=8888, help="port to listen on") define('config_file', default='secrets.cfg', help='filename for additional configuration') define('debug', default=False, group='application', help="run in debug mode (with automatic reloading)") # The following settings should probably be defined in secrets.cfg define('twitter_consumer_key', type=str, group='application') define('twitter_consumer_secret', type=str, group='application') define('cookie_secret', type=str, group='application', default='__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE__',
def main(): # The -W command-line option does not work in a virtualenv with # python 3 (as of virtualenv 1.7), so configure warnings # programmatically instead. import warnings # Be strict about most warnings. This also turns on warnings that are # ignored by default, including DeprecationWarnings and # python 3.2's ResourceWarnings. warnings.filterwarnings("error") # setuptools sometimes gives ImportWarnings about things that are on # sys.path even if they're not being used. warnings.filterwarnings("ignore", category=ImportWarning) # Tornado generally shouldn't use anything deprecated, but some of # our dependencies do (last match wins). warnings.filterwarnings("ignore", category=DeprecationWarning) warnings.filterwarnings("error", category=DeprecationWarning, module=r"tornado\..*") warnings.filterwarnings("ignore", category=PendingDeprecationWarning) warnings.filterwarnings("error", category=PendingDeprecationWarning, module=r"tornado\..*") # The unittest module is aggressive about deprecating redundant methods, # leaving some without non-deprecated spellings that work on both # 2.7 and 3.2 warnings.filterwarnings("ignore", category=DeprecationWarning, message="Please use assert.* instead") # unittest2 0.6 on py26 reports these as PendingDeprecationWarnings # instead of DeprecationWarnings. warnings.filterwarnings("ignore", category=PendingDeprecationWarning, message="Please use assert.* instead") # Twisted 15.0.0 triggers some warnings on py3 with -bb. warnings.filterwarnings("ignore", category=BytesWarning, module=r"twisted\..*") # The __aiter__ protocol changed in python 3.5.2. # Silence the warning until we can drop 3.5.[01]. warnings.filterwarnings("ignore", category=PendingDeprecationWarning, message=".*legacy __aiter__ protocol") logging.getLogger("tornado.access").setLevel(logging.CRITICAL) define('httpclient', type=str, default=None, callback=lambda s: AsyncHTTPClient.configure( s, defaults=dict(allow_ipv6=False))) define('httpserver', type=str, default=None, callback=HTTPServer.configure) define('ioloop', type=str, default=None) define('ioloop_time_monotonic', default=False) define('resolver', type=str, default=None, callback=Resolver.configure) define('debug_gc', type=str, multiple=True, help="A comma-separated list of gc module debug constants, " "e.g. DEBUG_STATS or DEBUG_COLLECTABLE,DEBUG_OBJECTS", callback=lambda values: gc.set_debug( reduce(operator.or_, (getattr(gc, v) for v in values)))) define('locale', type=str, default=None, callback=lambda x: locale.setlocale(locale.LC_ALL, x)) def configure_ioloop(): kwargs = {} if options.ioloop_time_monotonic: from censiotornado.platform.auto import monotonic_time if monotonic_time is None: raise RuntimeError("monotonic clock not found") kwargs['time_func'] = monotonic_time if options.ioloop or kwargs: IOLoop.configure(options.ioloop, **kwargs) add_parse_callback(configure_ioloop) log_counter = LogCounter() add_parse_callback( lambda: logging.getLogger().handlers[0].addFilter(log_counter)) import censiotornado.testing kwargs = {} if sys.version_info >= (3, 2): # HACK: unittest.main will make its own changes to the warning # configuration, which may conflict with the settings above # or command-line flags like -bb. Passing warnings=False # suppresses this behavior, although this looks like an implementation # detail. http://bugs.python.org/issue15626 kwargs['warnings'] = False kwargs['testRunner'] = TornadoTextTestRunner try: censiotornado.testing.main(**kwargs) finally: # The tests should run clean; consider it a failure if they logged # any warnings or errors. We'd like to ban info logs too, but # we can't count them cleanly due to interactions with LogTrapTestCase. if log_counter.warning_count > 0 or log_counter.error_count > 0: logging.error("logged %d warnings and %d errors", log_counter.warning_count, log_counter.error_count) sys.exit(1)
#!/usr/bin/env python # # A simple benchmark of tornado template rendering, based on # https://github.com/mitsuhiko/jinja2/blob/master/examples/bench.py import sys from timeit import Timer from censiotornado.options import options, define, parse_command_line from censiotornado.template import Template define('num', default=100, help='number of iterations') define('dump', default=False, help='print template generated code and exit') context = { 'page_title': 'mitsuhiko\'s benchmark', 'table': [ dict(a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8, i=9, j=10) for x in range(1000) ] } tmpl = Template("""\ <!doctype html> <html> <head> <title>{{ page_title }}</title> </head> <body> <div class="header">
from censiotornado import gen from censiotornado.ioloop import IOLoop from censiotornado.netutil import Resolver, ThreadedResolver from censiotornado.options import parse_command_line, define, options try: import twisted except ImportError: twisted = None try: import pycares except ImportError: pycares = None define('family', default='unspec', help='Address family to query: unspec, inet, or inet6') @gen.coroutine def main(): args = parse_command_line() if not args: args = ['localhost', 'www.google.com', 'www.facebook.com', 'www.dropbox.com'] resolvers = [Resolver(), ThreadedResolver()] if twisted is not None: from censiotornado.platform.twisted import TwistedResolver resolvers.append(TwistedResolver())
from __future__ import print_function from censiotornado.ioloop import IOLoop from censiotornado import gen from censiotornado.tcpclient import TCPClient from censiotornado.options import options, define define("host", default="localhost", help="TCP server host") define("port", default=9888, help="TCP port to connect to") define("message", default="ping", help="Message to send") @gen.coroutine def send_message(): stream = yield TCPClient().connect(options.host, options.port) yield stream.write((options.message + "\n").encode()) print("Sent to server:", options.message) reply = yield stream.read_until(b"\n") print("Response from server:", reply.decode().strip()) if __name__ == "__main__": options.parse_command_line() IOLoop.current().run_sync(send_message)
#!/usr/bin/env python from censiotornado.ioloop import IOLoop from censiotornado.options import define, options, parse_command_line from censiotornado.websocket import WebSocketHandler from censiotornado.web import Application define('port', default=9000) class EchoHandler(WebSocketHandler): def on_message(self, message): self.write_message(message, binary=isinstance(message, bytes)) def get_compression_options(self): return {} if __name__ == '__main__': parse_command_line() app = Application([ ('/', EchoHandler), ]) app.listen(options.port, address='127.0.0.1') IOLoop.instance().start()
import logging from censiotornado.ioloop import IOLoop from censiotornado import gen from censiotornado.iostream import StreamClosedError from censiotornado.tcpserver import TCPServer from censiotornado.options import options, define define("port", default=9888, help="TCP port to listen on") logger = logging.getLogger(__name__) class EchoServer(TCPServer): @gen.coroutine def handle_stream(self, stream, address): while True: try: data = yield stream.read_until(b"\n") logger.info("Received bytes: %s", data) if not data.endswith(b"\n"): data = data + b"\n" yield stream.write(data) except StreamClosedError: logger.warning("Lost client at host %s", address[0]) break except Exception as e: print(e) if __name__ == "__main__": options.parse_command_line() server = EchoServer()
#!/usr/bin/env python import logging from censiotornado import gen from censiotornado.ioloop import IOLoop from censiotornado.options import define, options, parse_command_line from censiotornado.websocket import websocket_connect define('url', default='ws://localhost:9001') define('name', default='Tornado') @gen.engine def run_tests(): url = options.url + '/getCaseCount' control_ws = yield websocket_connect(url, None) num_tests = int((yield control_ws.read_message())) logging.info('running %d cases', num_tests) msg = yield control_ws.read_message() assert msg is None for i in range(1, num_tests + 1): logging.info('running test case %d', i) url = options.url + '/runCase?case=%d&agent=%s' % (i, options.name) test_ws = yield websocket_connect(url, None, compression_options={}) while True: message = yield test_ws.read_message() if message is None: break test_ws.write_message(message, binary=isinstance(message, bytes))
#!/usr/bin/env python # # A simple benchmark of the tornado.gen module. # Runs in two modes, testing new-style (@coroutine and Futures) # and old-style (@engine and Tasks) coroutines. from timeit import Timer from censiotornado import gen from censiotornado.options import options, define, parse_command_line define('num', default=10000, help='number of iterations') # These benchmarks are delicate. They hit various fast-paths in the gen # machinery in order to stay synchronous so we don't need an IOLoop. # This removes noise from the results, but it's easy to change things # in a way that completely invalidates the results. @gen.engine def e2(callback): callback() @gen.engine def e1(): for i in range(10): yield gen.Task(e2) @gen.coroutine def c2(): pass
def define_logging_options(options=None): """Add logging-related flags to ``options``. These options are present automatically on the default options instance; this method is only necessary if you have created your own `.OptionParser`. .. versionadded:: 4.2 This function existed in prior versions but was broken and undocumented until 4.2. """ if options is None: # late import to prevent cycle import censiotornado.options options = censiotornado.options.options options.define("logging", default="info", help=("Set the Python log level. If 'none', tornado won't touch the " "logging configuration."), metavar="debug|info|warning|error|none") options.define("log_to_stderr", type=bool, default=None, help=("Send log output to stderr (colorized if possible). " "By default use stderr if --log_file_prefix is not set and " "no other logging is configured.")) options.define("log_file_prefix", type=str, default=None, metavar="PATH", help=("Path prefix for log files. " "Note that if you are running multiple tornado processes, " "log_file_prefix must be different for each of them (e.g. " "include the port number)")) options.define("log_file_max_size", type=int, default=100 * 1000 * 1000, help="max size of log files before rollover") options.define("log_file_num_backups", type=int, default=10, help="number of log files to keep") options.define("log_rotate_when", type=str, default='midnight', help=("specify the type of TimedRotatingFileHandler interval " "other options:('S', 'M', 'H', 'D', 'W0'-'W6')")) options.define("log_rotate_interval", type=int, default=1, help="The interval value of timed rotating") options.define("log_rotate_mode", type=str, default='size', help="The mode of rotating files(time or size)") options.add_parse_callback(lambda: enable_pretty_logging(options))
Authentication, error handling, etc are left as an exercise for the reader :) """ import logging import censiotornado.escape import censiotornado.ioloop import censiotornado.options import censiotornado.web import censiotornado.websocket import os.path import uuid from censiotornado.options import define, options define("port", default=8888, help="run on the given port", type=int) class Application(censiotornado.web.Application): def __init__(self): handlers = [ (r"/", MainHandler), (r"/chatsocket", ChatSocketHandler), ] settings = dict( cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", template_path=os.path.join(os.path.dirname(__file__), "templates"), static_path=os.path.join(os.path.dirname(__file__), "static"), xsrf_cookies=True, ) super(Application, self).__init__(handlers, **settings)
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import os.path import censiotornado.auth import censiotornado.escape import censiotornado.httpserver import censiotornado.ioloop import censiotornado.options import censiotornado.web from censiotornado.options import define, options define("port", default=8888, help="run on the given port", type=int) define("facebook_api_key", help="your Facebook application API key", type=str) define("facebook_secret", help="your Facebook application secret", type=str) class Application(censiotornado.web.Application): def __init__(self): handlers = [ (r"/", MainHandler), (r"/auth/login", AuthLoginHandler), (r"/auth/logout", AuthLogoutHandler), ] settings = dict( cookie_secret="__TODO:_GENERATE_YOUR_OWN_RANDOM_VALUE_HERE__", login_url="/auth/login", template_path=os.path.join(os.path.dirname(__file__), "templates"),