Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow predicate values to participate in view weighting #1863

Open
mmerickel opened this issue Jul 30, 2015 · 5 comments
Open

allow predicate values to participate in view weighting #1863

mmerickel opened this issue Jul 30, 2015 · 5 comments

Comments

@mmerickel
Copy link
Member

Copied from a paste in #pyramid irc:

@view_config(
    name='example',
    renderer='example_v2.mako',
    request_param=('foo', 'version=2'))
@view_config(
    name='example',
    renderer='example.mako',
    request_param='foo')
def example_view(self):
  return {}

# >>> GET /example
# HTTP 404 as expected, `foo` parameter not provided

# >>> GET /example?foo
# This renders the example.mako template

# >>> GET /example?foo&version=2
# This renders the example.mako template. Would want the example_v2.mako template
# to render, as it fits -all- of its request_params, which provide for a stricter match.

# N.B. Shuffling view_config statements around provides a solution, the following does
# follow my expectations, though relies on order in code, which I'd like to avoid:


@view_config(
    name='example',
    renderer='example.mako',
    request_param='foo')
@view_config(
    name='example',
    renderer='example_v2.mako',
    request_param=('foo', 'version=2'))
def example_view(self):
  return {}

Basically the two views have different values for their request_param predicate but they do not conflict and are ambiguously ordered. This strategy only works if the predicate values are mutually exclusive such that no value in one view is a subset of values in another view.

We should add a new sortable attribute to predicates or use the phash itself to contribute to the weighting such that 2 views with the same predicate but different values can be sorted appropriately.

@merwok
Copy link
Contributor

merwok commented Feb 9, 2020

I’m interested to take this

@mmerickel
Copy link
Member Author

I've thought about this issue for a long time and I don't have a viable solution. I think it's deceivingly difficult. Definitely open to some ideas, but I think it'll require some predicate extensions that are not clear to me right now to allow a predicate to provide a local weighting value that Pyramid would then incorporate into the top-level weighting that Pyramid uses.

@mmerickel
Copy link
Member Author

mmerickel commented Feb 10, 2020

The easiest thing I've got is to add some optional method to a predicate that exposes a weight between 0 and 1. Something like IPredicate.weight. Pyramid can then scale that into the specific predicate's weighting value. Even better might be to support some IPredicate.__cmp__ protocol that works between predicates of the same type. Pyramid already sorts predicates by type, so it's just within-type that we care about which is easy-ish for a specific predicate class to deal with.

@merwok
Copy link
Contributor

merwok commented Jul 2, 2020

Even better might be to support some IPredicate.__cmp__ protocol that works between predicates of the same type. Pyramid already sorts predicates by type, so it's just within-type that we care about which is easy-ish for a specific predicate class to deal with.

With Python 3, comparisons between different types are blocked by default, so the standard __lt__ could work here.

(I couldn’t say if your reference to __cmp__ was the Python 2 comparison method or an idea for another Pyramid name using double underscores despite not being defined by Python language)

I think my interest came from the bug I had in a custom predicate which made me think that it was not possible to have custom_thing=True and custom_thing=False, which actually works. Nonetheless I see the value in getting proper ordering and match preference for configs like request_param="foo", request_param="foo=spam", request_param=("foo=spam", "bar"), request_param=("foo=spam", "bar=eggs"). I have time to spend so could look into your idea!

@mmerickel
Copy link
Member Author

Yeah the feature is specifically around comparing predicate instances of the same type so definitely __lt__ stuff could make sense if that isn't buying us into too many restrictions / contracts around python's standard object comparison protocols.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants