Upgrading from earlier versions of Fresco

Make sure you read the CHANGELOG before you update your application to a newer version of Fresco.

Fresco releases have version numbers in the form x.y.z. The major version is x.y, and z is the minor version number. Minor releases will be backwards compatible with the previous minor release.

Occasionally features will be deprecated in a new release, pending later removal. By default Python does not show DeprecationWarnings. To ensure that you see these warnings, always run your application with python’s -Wd command line option, or set the environment variable PYTHONWARNINGS=d. Add this line to your shell’s configuration file (eg .zshrc or .bashrc) to enable this by default:

export PYTHONWARNINGS=d

Upgrading from Pesto

Fresco was originally based on the Pesto library. While Fresco is not backwards compatible, it does provide a reasonably straightforward migration path for applications written using Pesto.

Changes to view functions

View functions are no longer passed a Request object as the first parameter. Therefore it is necessary to remove this from your view function definitions. Where your views access request, this must be changed to context.request. For example:

def contact_form(request):
    send_email(request.get('name'), request.get('message'))

Becomes:

from fresco import context

def contact_form():
    request = context.request
    send_email(request.get('name'), request.get('message'))

Changes to routing

  1. Replace any instances of DispatcherApp() with FrescoApp()

  2. Replace @app.match calls with @app.route. For example:

from pesto import DispatcherApp
app = DispatcherApp()

@app.match('/home', 'GET')
...

Becomes:

from fresco import FrescoApp, GET
app = FrescoApp()

@app.route('/home', GET)
...
  1. If you specify multiple HTTP methods in a route, you must now use a list:

@app.match('/form', 'GET', 'POST')

Becomes:

@app.route('/form', [GET, POST])

Changes to URL generation

  1. The urlfor function is now preferred over the .url method. Both are supported for the time being, but you should change to urlfor to guarantee future compatibility.

    The names of keyword arguments to the .url method have also changed and require a leading underscore:

    myview.url(query={'id': 123})
    

    Becomes:

    urlfor(myview, _query={'id': 123})
    

    The following command line should help you track down any calls that need to be changed:s

    $ grep -re 'url([^)]*\(query\|script_name\|request\|scheme\|script_name\|fragment\)=' myproject/
    
  2. The request argument may no longer be passed as a positional argument to url:

    myview.url(request)
    

    Becomes:

    urlfor(myview, _request=request)
    

    The following command line should help you track down any calls that need to be changed:

    $ grep -re 'url(request' myproject/
    

Changes to middleware configuration

You should use the add_middleware to add the middleware:

app = DispatcherApp()
...

def app_factory(config, **kwargs):
    app = mymiddleware(app, 'foo', bar=True)
    return app

Becomes:

app = FrescoApp()

def app_factory(config, **kwargs):
    app.add_middleware(mymiddleware, 'foo', bar=True)
    return app

Changes to the Request object

Some property and method names have changed from pesto:

  • request.request_method is now request.method

  • request.request_path is now request.path

  • request.request_uri is now request.url

  • request.parsed_uri is now request.parsed_url

  • request.application_uri is now request.application_url

  • request.make_uri is now request.make_url

The following command line should help you track down any calls that need to be changed:

$ grep -re 'request\.\(request_method\|request_path\|request_uri\|application_uri\|make_uri\)' myproject/

The path_info and script_name arguments of request.make_url should now be upper cased, eg:

request.make_uri(path_info='/')

Becomes:

request.make_url(PATH_INFO='/')

Other changes

  • Change all references to pesto.currentrequest() to fresco.currentrequest()

Compatibility shims

The code shown below is unsupported and not recommended for anything other than temporary fixes while you migrate a large code base.

Monkey patch pesto.currentrequest to replace it with fresco’s version:

import pesto
import fresco

pesto.currentrequest = fresco.currentrequest

Adapt pesto DispatcherApp instances to work in a Fresco application:

from pesto.dispatch import ExtensiblePattern as PestoExtensiblePattern
from fresco.routing import ExtensiblePattern as FrescoExtensiblePattern
from fresco import Route

def pesto_routing_adapter(dispatcher):
  """\
  Take a pesto DispatcherApp and adapt routing definitions to the format
  required by fresco
  """

  dispatcher.__routes__ = []
  for pattern, predicate, methods in dispatcher.patterns:
     if isinstance(pattern, PestoExtensiblePattern):
           pattern = FrescoExtensiblePattern(pattern.pattern,
                                             name=pattern.name)
     for m, func in methods.items():
        dispatcher.__routes__.append(Route(pattern, m, func,
                                           predicate=predicate))
  return dispatcher

app = FrescoApp()
app.include('', pesto_routing_adapter(my_dispatcher_app)

Preserve request object API compability by substituting a hybrid request class that also inherits from the (largely compatible) pesto request class:

from fresco.request import Request as FrescoRequest
from pesto.request import Request as PestoRequest

import fresco

class FrankenRequest(FrescoRequest, PestoRequest):
    pass

app = FrescoApp()
app.request_class = FrankenRequest