Commits

Anonymous committed e61356d

Changed page UpgradeTo22

  • Participants
  • Parent commits e4ec869

Comments (0)

Files changed (1)

File UpgradeTo22.wiki

+== How to upgrade to CherryPy 2.2 ==
+
+This page discusses changes between CherryPy 2.1 (October 2005) and 2.2 (February 2006) which might require you to modify your code when you upgrade. Bugfixes aren't listed here. 
+
+=== CamelCase changed to lowercase_with_underscores ===
+
+In keeping with [http://www.python.org/dev/peps/pep-0008/ PEP 8], most of CherryPy's API has been changed from CamelCase identifiers to lowercase_with_underscores. See the bottom of this page for a list of the names that have changed. However, every effort has been made to allow you to continue using the CamelCase names (until the next major or minor version).  To repeat: both forms of each name should work in 2.2. So change when you can.
+
+There's a new "cherrypy.lowercase_api" flag, so that users can say "I'm using the new lowercase API" and get a (small) speed boost from it.
+
+=== Positional Parameters ===
+
+In CherryPy 2.1, you had to use a special class to make your handler methods "Positional Params Aware" (that is, turn "/handler/extra/path/info" into {{{handler("extra", "path", "info")}}}). Starting with [786], any method (except "index") may now receive positional params. Read [http://www.cherrypy.org/trunk/docs/book/chunk/ch03.html#id3226503 3.1 in the book] for a detailed look at mapping and parameters.
+
+=== Changing which handler gets called ===
+
+In CherryPy 2.1, if you needed to change which method handles a given URL, you might have changed cherrypy.request.path. In 2.2, you should always change cherrypy.request.object_path instead. See [760] and #373.
+
+=== Multiple apps and virtual paths ===
+
+Mounting a CherryPy app at a mount point determined at runtime was very difficult in 2.1. There's a new _cptree.Tree class in 2.2 to make this easier. '''In general, you should stop writing'''
+{{{
+cherrypy.root = Root()
+}}}
+'''and instead write'''
+{{{
+cherrypy.tree.mount(Root(), baseurl="/path/to/app", conf=config)
+}}}
+
+This new method will mount your app at the appropriate branch on the cherrypy.root tree, and will also auto-prefix the section-paths in the config dict you supply. If you don't supply the baseurl arg, it will look for a "mount_point" config entry in {{{[global]}}} and use that.
+
+The "old way" of writing {{{cherrypy.root = AppRoot()}}} will still work, but restricts your app to being mounted at "/", and may preclude other applications from being mounted on the same server.
+
+=== server.environment ===
+
+The behavior of each "server.environment" (such as "development", "staging", and "production") was hard-coded into the core in 2.1. Beginning with [761], these behaviors are encapsulated in cherrypy.config.environments. This allows you to write an application that modifies the builtin environments, or adds new named environments, to give your deployers flexibility that is specific to the needs of your application.
+
+=== Error handling ===
+
+CherryPy 2.2 makes the distinction between ''HTTP errors'' (return codes between 400 and 599) and ''unhandled exceptions'' (which will result in a 500 return code) a bit more explicit. You override the response to ''unhandled exceptions'' with {{{_cpOnError}}}. To override the response to ''HTTP errors'', there's a new {{{_cpOnHTTPError(status, message)}}} function. See [771].
+
+There's also a new "server.log_unhandled_tracebacks" config entry (see [805]), which is distinct from "server.log_tracebacks".
+
+The {{{cherrypy.log}}} function grew a new "traceback" argument and made the msg argument optional. It was:
+
+{{{
+log(msg, context='', severity=0)
+}}}
+
+and is now:
+
+{{{
+log(msg='', context='', severity=0, traceback=False)
+}}}
+
+=== Response.body ===
+
+cherrypy.response.body is now a descriptor, which means that '''anytime''' you set .body now it will be coerced to an iterable. There's a new response.collapse_body() function (mostly for use in filters), which collapses the body into a single new_body string, sets response.body to [new_body], and returns new_body.
+
+There's also a new request.execute_main flag (bool), to govern whether the Request.main method is called. This replaces the old behavior, where main would be called "if response.body is None". There may be custom before_main filters which depend on the old behavior, and need to be updated to set request.execute_main = False (instead of just relying on setting body).
+
+=== Just Plain Gone (or otherwise mangled) ===
+
+ * [772] removed cherrypyrequest.paramList and cherrypy.request.originalParamList. These were only used by xmlrpcfilter, and it was better to keep that functionality entirely in the filter without stuffing it into the core.
+ * [777] changed root._global to root.global_. If you don't define it, there's a new default _cpGlobalHandler in _cputil which will be called.
+ * Lots of functionality that isn't CherryPy-specific got moved into a new, improved lib/httptools.py module. If you're looking for something from 2.1 and can't find it, look in httptools first.
+ * cherrypy.request.browser_url is now a read-only property, since it is a calculated value. If you want to change its value now, change request.base, path, or query_string, and it will be updated automatically. See [793].
+ * cherrypy.request.originalParamMap is deprecated in 2.2, and will be removed in 2.3.
+ * [839] removed the custom exceptions !WrongResponseType and !WrongUnreprValue.
+ * cptools.serveFile now requires absolute paths. See [909].
+
+=== Filter changes ===
+
+ * cherrypy/lib/filter has been moved to cherrypy/filters (but the old location should still work until CP 2.3).
+ * New on_end_request filter method, which runs after the entire response has been written out. See [838].
+ * xmlrpcfilter no longer allows None as a response value. See [785].
+ * If staticfilter didn't find a file, it used to error. Now it proceeds, trying to find a dynamic handler (like any other request). See [878].
+ * The before_main filter hook can now raise InternalRedirect. See [879] and #55.
+ * The !VirtualHostFilter has been reinstated. See [883] and #344.
+ * Staticfilter now requires absolute paths. See [909]. The easiest way to do this is to provide a "static_filter.root" config entry.
+ * The internals filter architecture changed. The config options server.filtersRoot, server.inputFiltersDict and server.outputFiltersDict were removed in [807] in favor of a code-bound solution. The attributes filter._input_order and _output_order used to each be a list of class names (like 'CacheFilter'). They are now called {{{filters.input_filters}}} and {{{filters.output_filters}}}, and each is now a list of full dotted-package-class-names (like "cherrypy.filters.cachefilter.CacheFilter"). This means you can now insert your own classes (either classname strings or the filter class itself) in each list; they are invoked in order. See [891] and [903].
+ * All on_start_resource and on_end_request filter methods are now guaranteed to run, even if there are failures in other on_start or on_end methods. This is NOT true of the other filter methods. See [911].
+ * Having staticfilter on doesn't automatically disable sessionfilter anymore. See [960].
+ * The sessionfilter now sets "Expires" instead of "Max-Age" for the session cookie. See [963].
+ * sessionauthenticatefilter has new "on_login" and "on_logout" callbacks. See [971].
+
+=== HTTP Servers ===
+
+First, [973] removed the deprecated _cphttpserver module. Use _cpwsgiserver instead, which now has AF_UNIX support and respects server.socket_queue_size. It can also mount multiple apps, now, see [965] through [967].
+
+Second, cherrypy.server.start has a new optional "server" argument, so you can pass in an instance of an HTTP server instead of just a class.
+
+Third, if you have a custom HTTP server, the API for submitting requests to the CherryPy core has changed (see [758]). You no longer need to call {{{request.purge__()}}} and {{{response.purge__()}}}; instead, write code like the following:
+
+{{{
+#!python
+request = cherrypy.server.request(client_address, remote_host)
+request.multithread = True
+request.multiprocess = False
+response = request.run(raw_requestline, headerlist, rfile)
+}}}
+
+Note that the arguments which used to all be passed to request() are now split up between the constructor and the run() method. When you're ready to write out the response, use the response object returned from request.run() instead of using cherrypy.response.
+
+In order to facilitate the new on_end_request filter method, you also '''must call request.close()''' once your HTTP server has completely written out the response to the client. See [838] and [851].
+
+Finally, if you patched _cpwsgiserver to handle some socket errors, you should revert those patches (some were fixed) and add any new error codes to _cpwsgiserver.socket_errors_to_ignore instead.
+
+=== The Request object ===
+
+The Request class in _cphttptools has changed, as well. It used to create cherrypy.request, now it *is* cherrypy.request.
+
+=== Test suite changes ===
+
+The test suite has been reorganized to allow testing with other WSGI servers. Basically, you have to write future tests as if the server-side and client-side run in separate processes. If you wrote tests for your application using the tools in CherryPy's test suite, you may have to rewrite them so that they also obey this separation.
+
+
+=== Name changes ===
+
+''' The old variable names will still work until at least CherryPy-2.3, but they are considered deprecated '''
+
+Variables:
+
+||	'''Old name'''	||	'''New name'''	||
+||	cherrypy.threadData	||	cherrypy.thread_data
+||	request.paramMap	||	request.params
+||	request.queryString	||	request.query_string
+||	request.headerMap	||	request.headers
+||	request.browserUrl	||	request.browser_url
+||	request.simpleCookie	||	request.simple_cookie
+||	request.objectPath	||	request.object_path
+||      request.remoteAddr      ||      request.remote_addr
+||      request.remoteHost      ||      request.remote_host
+||      request.remotePort      ||      request.remote_port
+||	response.headers	||	response.header_list
+||	response.headerMap	||	response.headers
+||	response.simpleCookie	||	response.simple_cookie
+||	server.onStartServerList	||	server.on_start_server_list
+||	server.onStartThreadList	||	server.on_start_thread_list
+||	server.onStopThreadList	||	server.on_stop_thread_list
+||	server.onStopServerList	||	server.on_stop_server_list
+||	cherrypy.config.configMap	||	cherrypy.config.configs
+||	_cpLogAccess	||	_cp_log_access
+||	_cpOnError	||	_cp_on_error
+||	_cpLogMessage	||	_cp_log_message
+||	_cpOnHTTPError	||	_cp_on_http_error
+||	_cpFilterList	||	_cp_filters
+
+Config options:
+||	'''Old name'''	||	'''New name'''	||
+||	server.threadPool	||	server.thread_pool	||
+||	server.socketPort	||	server.socket_port	||
+||	server.socketHost	||	server.socket_host	||
+||	server.logToScreen	||	server.log_to_screen	||
+||	server.logFile	||	server.log_file	||
+||	server.logFileNotFound	||	server.log_file_not_found	||
+||	server.showTracebacks	||	server.show_tracebacks	||
+||	server.logRequestHeaders	||	server.log_request_headers	||
+||	server.socketQueueSize	||	server.socket_queue_size	||
+||	server.logConfigOptions	||	server.log_config_options	||
+||	server.reverseDNS	||	server.reverse_dns	||
+||	server.logTracebacks	||	server.log_tracebacks	||
+||	server.logUnhandledTracebacks	||	server.log_unhandled_tracebacks	||
+||	server.logToScreen	||	server.log_to_screen	||
+||	server.logAccessFile	||	server.log_access_file	||
+||	server.maxRequestHeaderSize	||	request.max_request_header_size	||
+||	server.protocolVersion	||	server.protocol_version	||
+||	errorPage	||	error_page	||
+||	server.maxRequestBodySize	||	server.max_request_body_size	||
+||	streamResponse	||	stream_response	||
+
+Filter config:
+||	'''Old name'''	||	'''New name'''	||
+||	baseUrlFilter.on	||	base_url_filter.on	||
+||	baseUrlFilter.baseUrl	||	base_url_filter.base_url	||
+||	baseUrlFilter.useXForwardedHost	||	base_url_filter.use_x_forwarded_host	||
+||	cacheFilter.on	||	cache_filter.on	||
+||	cacheFilter.key	||	cache_filter.key	||
+||	cacheFilter.delay	||	cache_filter.delay	||
+||	cacheFilter.maxobjsize	||	cache_filter.maxobjsize	||
+||	cacheFilter.maxsize	||	cache_filter.maxsize	||
+||	cacheFilter.maxobjects	||	cache_filter.maxobjects	||
+||	decodingFilter.on	||	decoding_filter.on	||
+||	decodingFilter.encoding	||	decoding_filter.encoding	||
+||	encodingFilter.on	||	encoding_filter.on	||
+||	encodingFilter.defaultEncoding	||	encoding_filter.default_encoding	||
+||	gzipFilter.on	||	gzip_filter.on	||
+||	gzipFilter.compresslevel	||	gzip_filter.compresslevel	||
+||	gzipFilter.mimeTypeList	||	gzip_filter.mime_types	||
+||	logDebugInfoFilter.on	||	log_debug_info_filter.on	||
+||	logDebugInfoFilter.mimeTypeList	||	log_debug_info_filter.mime_types	||
+||	logDebugInfoFilter.logAsComment	||	log_debug_info_filter.log_as_comment	||
+||	logDebugInfoFilter.logBuildTime	||	log_debug_info_filter.log_build_time	||
+||	logDebugInfoFilter.logPageSize	||	log_debug_info_filter.log_page_size	||
+||	logDebugInfoFilter.logSessionSize	||	log_debug_info_filter.log_session_size	||
+||	nsgmlsFilter.on	||	nsgmls_filter.on	||
+||	nsgmlsFilter.tmpDir	||	nsgmls_filter.tmp_dir	||
+||	nsgmlsFilter.nsgmlsPath	||	nsgmls_filter.nsgmls_path	||
+||	nsgmlsFilter.catalogPath	||	nsgmls_filter.catalog_path	||
+||	sessionAuthenticateFilter.on	||	session_authenticate_filter.on	||
+||	sessionAuthenticateFilter.checkLoginAndPassword	||	session_authenticate_filter.check_login_and_password	||
+||	sessionAuthenticateFilter.loginScreen	||	session_authenticate_filter.login_screen	||
+||	sessionAuthenticateFilter.notLoggedIn	||	session_authenticate_filter.not_logged_in	||
+||	sessionAuthenticateFilter.loadUserByUsername	||	session_authenticate_filter.load_user_by_username	||
+||	sessionAuthenticateFilter.sessionKey	||	session_authenticate_filter.session_key	||
+||	sessionFilter.on	||	session_filter.on	||
+||	sessionFilter.storageType	||	session_filter.storage_type	||
+||	sessionFilter.storagePath	||	session_filter.storage_path	||
+||	sessionFilter.timeout	||	session_filter.timeout	||
+||	sessionFilter.locking	||	session_filter.locking	||
+||	sessionFilter.onCreateSession	||	session_filter.on_create_session	||
+||	sessionFilter.onDeleteSession	||	session_filter.on_delete_session	||
+||	sessionFilter.cleanUpDelay	||	session_filter.clean_up_delay	||
+||	sessionFilter.cookieName	||	session_filter.cookie_name	||
+||	sessionFilter.deadlockTimeout	||	session_filter.deadlock_timeout	||
+||	sessionFilter.storageClass	||	session_filter.storage_class	||
+||	sessionFilter.getDB	||	session_filter.get_db	||
+||	xxx.acquireLock	||	xxx.acquire_lock	||
+||	xxx.releaseLock	||	xxx.release_lock	||
+||	xxx.cleanUp	||	xxx.clean_up	||
+||	staticFilter.on	||	static_filter.on	||
+||	staticFilter.match	||	static_filter.match	||
+||	staticFilter.file	||	static_filter.file	||
+||	staticFilter.dir	||	static_filter.dir	||
+||	staticFilter.root	||	static_filter.root	||
+||	tidyFilter.on	||	tidy_filter.on	||
+||	tidyFilter.tmpDir	||	tidy_filter.tmp_dir	||
+||	tidyFilter.strictXml	||	tidy_filter.strict_xml	||
+||	tidyFilter.tidyPath	||	tidy_filter.tidy_path	||
+||	tidyFilter.errorsToIgnore	||	tidy_filter.errorsToIgnore	||
+||	xmlRpcFilter.on	||	xmlrpc_filter.on	||
+||	xmlRpcFilterOn	||	xmlrpc_filter_on	||
+||	isRPC	||	is_rpc	||
+
+Fitler hooks:
+||	'''Old name'''	||	'''New name'''	||
+||	onStartResource	||	on_start_resource	||
+||	beforeRequestBody	||	before_request_body	||
+||	beforeMain	||	before_main	||
+||	beforeFinalize	||	before_finalize	||
+||	beforeErrorResponse	||	before_error_response	||
+||	afterErrorResponse	||	after_error_response	||
+||	onEndResource	||	on_end_resource	||
+||	onEndRequest	||	on_end_request	||
+
+Method parameters:
+||	'''Old name'''	||	'''New name'''	||
+||	initOnly	||	init_only	||
+||	serverClass	||	server_class	||