On Sun, May 26, 2013 at 15:37 +0000, Jason R. Coombs wrote: > No. I haven't seen that syntax much if at all. I suggest it because it > appeals to my aesthetic.
that's fine :) > I'm not sure the distinction between class and decorator is so clear. After > all, a decorator is just a callable with a particular signature. I haven't > considered the implementation, but I imagine pytest.fixture could in fact be > a class if you wanted it to be. it could but decorators are typically functions. > Even if fixture is only a factory function, it's conceivable that the > alternate function could be appended as an attribute: > > def fixture(...): > # primary behavior > > def _yielding_fixture(*args, **kwargs): > # wrap or alter behavior of fixture(*args, **kwargs) > > fixture.yielding = _yielding_fixture sure, that's possible. > I agree the implementation is a little clumsy, but I would be inclined to > accept a little bit of implementation cruft for a nicer exposed API. I claim it would be a bit of an unexpected API. Maybe someone else than us two can comment on it :) > That said, I'm not trying to convince, but only to share. If you don't love > the idea, I won't be offended if you don't incorporate it. thanks for the relaxedness. > Sent from Earth :) holger > > On May 26, 2013, at 7:52, "holger krekel" <[email protected]> wrote: > > > Hi Jason, > > > > (your post contains a bit many blank lines, btw, deleting them :) > > > > On Sat, May 25, 2013 at 14:40 +0000, Jason R. Coombs wrote: > >> May I suggest an alternate idea: > >> > >> @pytest.fixture.context(.) > >> > >> def func(): > >> . > >> > >> Or > >> > >> @pytest.fixture.yielding(.) > >> > >> def func(): > >> . > >> > >> Depending on which mode is not supported by fixture directly. > >> > >> Then, the decorator can take the same signature as the natural usage > >> (@pytest.fixture), but alter the handling of a generator appropriately. It > >> can be thought of as an alternate constructor for the same fixture factory. > >> It provides a nice, namespaced name and doesn't threaten to pollute the > >> pytest namespace with a proliferation of fixture variants. > > > > Not cramming the pytest.* is a goal i share but i am not sure about > > this suggestion. The "idiomatic" way to introduce a decorator variant > > in Python is adding a keyword argument or a new name. > > > > Your suggested syntax reminds of what one does for classes, i.e. providing > > classmethods for alternate constructors. But i haven't seen it anywhere > > for decorators, did you? > > > > best, > > holger > > > >> > >> From: Pytest-dev [mailto:[email protected]] > >> On > >> Behalf Of Bruno Oliveira > >> Sent: Friday, 24 May, 2013 17:13 > >> To: holger krekel; Harro van der Klauw; Andreas Pelme; > >> [email protected] > >> Subject: Re: [pytest-dev] fixtures as context managers > >> > >> > >> > >> In light of the examples, IMHO, I agree that fixtures being explicit about > >> using yield as context-managers is preferable. > >> > >> > >> > >> I like @pytest.contextfixture, it is easy to look-up and understand since > >> it > >> mimics what we already have in contextlib. > >> > >> > >> > >> > >> > >> > >> > >> On Fri, May 24, 2013 at 12:07 PM, holger krekel <[email protected] > >> <mailto:[email protected]> > wrote: > >> > >> On Fri, May 24, 2013 at 16:50 +0200, Harro van der Klauw wrote: > >>> As long as it throws an error hinting that you might need yielding=True it > >>> should be obvious on how to fix > >>> the backwards incompatibility issue as soon as you run your tests. > >> > >> We cannot easily throw an error with a hint. Consider this example: > >> > >> import pytest > >> > >> > >> @pytest.fixture > >> def fix(): > >> yield 1 > >> yield 2 > >> > >> def test_fix(fix): > >> for x in fix: > >> assert x < 3 > >> > >> This runs fine on pytest-2.3.5. On trunk it gives this error: > >> > >> ... > >> > >> fix = 1 > >> > >> def test_fix(fix): > >>> for x in fix: > >> assert x < 3 > >> E TypeError: 'int' object is not iterable > >> > >> I've never written or seen somebody writing such a generator fixture, > >> though. > >> And what you would need to do is rewrite the fixture: > >> > >> @pytest.fixture > >> def fix(): > >> def gen(): > >> yield 1 > >> yield 2 > >> return gen() > >> > >> Then again, when i first saw the contextlib.contextmanager decorator > >> i found it not very intuitive. Did anyone? It looks like a hack. > >>> From that angle i'd rather go for requiring "contextyield=True" or > >> @pytest.contextfixture because that can be looked up in documentation > >> and thus is easier to read for people not familiar with yields/contextlib. > >> > >> best, > >> holger > >> > >> > >>> I don't see a big problem with this, updating of a requirement is > >> something > >>> that you should never do automatically. > >>> > >>> Cheers, > >>> Harro > >>> > >>> > >>> > >>> On 24 May 2013 16:36, Andreas Pelme <[email protected] > >> <mailto:[email protected]> > wrote: > >>> > >>>> On Thursday 9 May 2013 at 15:56, holger krekel wrote: > >>>>> This is probably used by very few people but to be on the safe side, > >>>>> we probably should introduce a flag like this: > >>>>> > >>>>> @pytest.fixture(ctx=True) # signal this is a context manager style > >>>> fixture > >>>>> def fix(): > >>>>> yield 1 > >>>>> > >>>>> What do you think? Any other suggestions for the flag name? > >>>>> > >>>>> I'd rather not introduce something like @pytest.contextfixture > >>>>> because it would be a duplication of the API (scope, params). > >>>>> But i am open to be convinced otherwise. > >>>> > >>>> I agree that another API like contextfixture should be avoided. > >>>> > >>>> We had a short discussion on IRC about this, Holger had the idea of > >> doing > >>>> the opposite if ctx=True - a new default argument "yielding=False" which > >>>> would make it possible to restore the old behavior by putting > >> yielding=True > >>>> on fixtures that would be affected by this. > >>>> > >>>> A fixture that is a generator that currently looks like this > >>>> > >>>> @pytest.fixture > >>>> def fix(): > >>>> yield 1 > >>>> yield 2 > >>>> > >>>> Would then have to be changed to > >>>> > >>>> @pytest.fixture(yielding=True) > >>>> def fix(): > >>>> yield 1 > >>>> yield 2 > >>>> > >>>> This is backward incompatible, but given that it seems questionable if > >>>> "generator fixtures" useful/is used, with a note in the release notes > >> and > >>>> documentation I think this could be a good compromise. > >>>> > >>>> I will be happy to give this a try if it is decided this could be a good > >>>> approach! > >>>> > >>>> Cheers > >>>> Andreas > >>>> > >>>> > >>>> _______________________________________________ > >>>> Pytest-dev mailing list > >>>> [email protected] <mailto:[email protected]> > >>>> http://mail.python.org/mailman/listinfo/pytest-dev > >> > >>> _______________________________________________ > >>> Pytest-dev mailing list > >>> [email protected] <mailto:[email protected]> > >>> http://mail.python.org/mailman/listinfo/pytest-dev > >> > >> _______________________________________________ > >> Pytest-dev mailing list > >> [email protected] <mailto:[email protected]> > >> http://mail.python.org/mailman/listinfo/pytest-dev > > > > > > _______________________________________________ Pytest-dev mailing list [email protected] http://mail.python.org/mailman/listinfo/pytest-dev
