CherryPy 3.2 having problems with aliases with a hyphen

guest avatarguest created an issue
  1. 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')
  1. 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:

    @expose
    def mediakit(foo):
        pass
    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?

    @expose(as="media-kit")
    def mediakit(foo):
        pass
    

    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

    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

    anonymous

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

    class AboutPage:
        @cherrypy.expose
            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:

    http://localhost:8080/media.kit
    http://localhost:8080/media_kit
    http://localhost:8080/media-kit
    http://localhost:8080/media+kit
    http://localhost:8080/media!kit
    http://localhost:8080/media@kit
    

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

    '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
    

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

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

    cherrypy:

    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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.