1. cherrypy
  2. CherryPy
Issue #1071 invalid

CherryPy 3.2 having problems with aliases with a hyphen

created an issue

This Does Not Work

{{{ class AboutPage: @cherrypy.expose(alias='media-kit') def mediakit(self, **params): return get_template('media-kit.html').render(title = 'Media Kit') }}}

This Works:

{{{ class AboutPage: @cherrypy.expose(alias='mediakit2') def mediakit(self, **params): return get_template('media-kit.html').render(title = 'Media Kit') }}}

Comments (5)

  1. Anonymous

    This could be fixed technically by adding another str.replace call in cherrypy.expose. But there are larger questions: is the bug author's intention to support both /mediakit and /media-kit? I suspect he/she only wants the latter. In that case, would the RoutesDispatcher be a better solution?

    From another angle, the alias API may be confusing. It provides a simplistic algorithm for translating "index.html" to "index_html", which gives the impression that it is designed not just for aliasing but also for simple routing. My understanding is that the alias API (besides the dot replacement) is equivalent to:

    def mediakit(foo):
    media_kit = mediakit

    That is, alias exposes a single call at multiple endpoints--N:1. Translating URL parts to Python names is 1:1.

    There may very well be another existing option here, but what about an "as" argument to expose?

    def mediakit(foo):

    This would take an string (raising an error if it includes forward slash) and provide a 1:1 mapping of that arbitrary URL part to the given Python function. If this were adopted then I would suggest the simplistic dot replacement currently with alias should be deprecated--it's sooooo Zope. ;-) And if the alias API is, at that point, syntactic sugar, I would suggest it for deprecation as well--"one obvious way".

  2. cherrypy repo owner

    The more complicating factor is that CherryPy already has a mechanism for converting 'index.html' to 'index_html' that doesn't use `expose` and is on by default: `_cpdispatch.Dispatcher.translate`, which is a str.translate mask. The `expose` decorator is really for exposing the same resource as both 'foo' and 'bar'. In the OP's case, they should just use the `translate` attribute instead of the `expose` decorator. If someone wants to expose both "media-kit" and "foo", they should use both.

  3. Anonymous


    If the OP wants to support /media-kit (but not /mediakit) he can use:

    class AboutPage:
            def media_kit(self, **params):
                return get_template('media-kit.html').render(title = 'Media Kit')

    Warning: because of the current translation, this even maps many urls to the media_kit page handler:


    ... and so on for most of the "string.punctuation" characters


    If for unknown reasons he persists to support both, he can use:

    class AboutPage:
            def mediakit(self, **params):
                return get_template('media-kit.html').render(title = 'Media Kit')


    Thanks for the pointer! That was really helpful. I looked up the changeset which introduces the translation: https://bitbucket.org/cherrypy/cherrypy/changeset/26eb235e1742#chg_cherrypy/_cpdispatch.py_newline200

    There is something which caught my attention. You see that in the dispatcher "objname = name.replace('.', '_')" gets replaced by "objname = name.translate(self.translate)" [line 280, cherrypy/_cpdispatch.py]. However "alias.replace('.', '_')" is kept (https://bitbucket.org/cherrypy/cherrypy/src/697c7af588b8/cherrypy/__init__.py#cl-331). Is it possible that this is a mistake? Should objname and alias not undergo the same translation to stay in sync? But the expose function has no access to the translation table of the dispatcher AFAIK. A solution is that the alias uses already translated strings (e.g. foo_bar instead of foo-bar).

    I suspect the current Cherrypy code will cause problems in the following corner case. Suppose we create a Dispatcher or MethodDispatcher with the following translation table:

    punctuation_to_X = string.maketrans(string.punctuation, 'X' * len(string.punctuation))

    The alias 'foo.bar' will fail as it behaves as punctuation_to_underscores (as defined in _cpdispatch, line 206). I see two solutions:

    • To add a note in the documentation that for the translation string you better stick to underscores or otherwise the alias will fail. (I am not in favor of this.)
    • IMHO the best fix would be to remove ".replace('.', '_')" from alias.

    Let me know if you need a patch (with testcase) for it, although it is very trivial to fix.

  4. Log in to comment