On Wed, Aug 31, 2022, 12:24 AM Wes Turner <wes.tur...@gmail.com> wrote:
> +0.1 > > > > > On Tue, Aug 30, 2022, 11:15 PM Charles Machalow <csm10...@gmail.com> > wrote: > > > >> ``` >> and for the simple test, added this to the partial definition: >> >> ``` >> @property >> def __name__(self): >> return f"partial({self.func.__name__})" >> ``` >> Of course it probably wouldn't be too bad to add in the args/kwargs to >> the __name__ (and eventually __qualname__) as well. >> > > That'd be real nice. IIRC default repr()'s present __name__ but not (yet) > __qualname__? > > From > https://docs.pytest.org/en/latest/how-to/parametrize.html#pytest-mark-parametrize-parametrizing-test-functions > ```quote > Note > Parameter values are passed as-is to tests (no copy whatsoever). > > For example, if you pass a list or a dict as a parameter value, and the > test case code mutates it, the mutations will be reflected in subsequent > test case calls. > > Note > pytest by default escapes any non-ascii characters used in unicode strings > for the parametrization because it has several downsides. If however you > would like to use unicode strings in parametrization and see them in the > terminal as is (non-escaped), use this option in your pytest.ini: > > [pytest] > disable_test_id_escaping_and_forfeit_all_rights_to_community_support = > True > > Keep in mind however that this might cause unwanted side effects and even > bugs depending on the OS used and plugins currently installed, so use it at > your own risk > ``` > > Re: punycode / idna: > https://gist.github.com/pessom/b6c8c4d55296e5439403ae3cc942fbbc : > > >>> x="🖥️"; print((x, x.encode('idna')); assert x = > x.encode('idna').decode('idna') > > >> This was with commenting out using the C-version of partial and just >> playing with the Python version. If folks think this (cleaned up) could >> make upstream, I'd be happy to try to get a PR together for first allowing >> __qualname__ to be a property then what we're talking about here. >> > > +0.1 > > >> - Charlie Scott Machalow >> >> >> On Tue, Aug 30, 2022 at 7:08 PM Joao S. O. Bueno <gwid...@gmail.com> >> wrote: >> >>> Actually, there is a good motive IMO for a partial function to have >>> __name__ and __qualname__: the code one is passing a partial function >>> might expect these attributes to be presented in the callable it get. >>> >>> It is just a matter of unifying the interface for callables that are >>> often used as arguments in calls, and as such, even >>> if __name__ and __qualname__ are fixed and immutable strings, this would >>> be an improvement. >>> (say, a partial callable __name__ could be fixed to "<partial>" just as >>> a lambda's __name__ is "<lambda>") >>> >>> On Tue, Aug 30, 2022 at 4:29 PM Wes Turner <wes.tur...@gmail.com> wrote: >>> >>>> Would a property or a copy be faster for existing and possible use >>>> cases? In practice, how frequently will __qual/name__ be called on >>>> partials? >>>> >>>> - Copying __qual/name__ would definitely be a performance regression >>>> >>>> - There are probably as many use cases for partials as other methods of >>>> functional composition, >>>> - __qual/name__ support is not yet extant >>>> >>>> - it's faster to run e.g. a grid search *without* partials, due to >>>> function call overhead, due to scope allocation on the stack in stackful >>>> pythons [1] >>>> >>>> [1] Hyper Parameter Search > Scaling hyperparameter searches >>>> >>>> https://ml.dask.org/hyper-parameter-search.html#scaling-hyperparameter-searches >>>> >>>> [2] Pipeline caching in TPOT >>>> http://epistasislab.github.io/tpot/using/#pipeline-caching-in-tpot >>>> #parallel-training-with-dask ; TPOT generates actual python source >>>> code instead of an ensemble of partials >>>> >>>> >>>> >>>> >>>> >>>> On Tue, Aug 30, 2022, 12:07 PM Charles Machalow <csm10...@gmail.com> >>>> wrote: >>>> >>>>> We may be able to do __name__/__qualname__ as a property to make it >>>>> evaluate when called as opposed to computed once on creation. That way we >>>>> just work with .func upon call so no need for extra references, etc. >>>>> >>>>> As for documentation generation tools, it may be different at first, >>>>> though I believe the existing ispartial checks would catch partials still. >>>>> If they want to (in a new version) swap to using __name__/__qualname__ >>>>> that >>>>> should be fine, but this likely wouldn't inherently break existing tools. >>>>> >>>>> - Charlie Scott Machalow >>>>> >>>>> >>>>> On Mon, Aug 29, 2022 at 11:08 PM Wes Turner <wes.tur...@gmail.com> >>>>> wrote: >>>>> >>>>>> Is there a non-performance regressive way to proxy attr access to >>>>>> func.__name__ of the partial function (or method; Callable)? >>>>>> >>>>>> Would this affect documentation generation tools like e.g. >>>>>> sphinx-spidoc, which IIRC use __name__ and probably now __qualname__ for >>>>>> generating argspecs in RST for HTML and LaTeX? >>>>>> >>>>>> >>>>>> - https://docs.python.org/3/library/inspect.html >>>>>> - functions and methods have __name__ and __qualname__ >>>>>> - see: sphinx.utils.inspect >>>>>> >>>>>> - https://docs.python.org/3/library/functools.html#functools.partial >>>>>> - >>>>>> https://docs.python.org/3/library/functools.html#functools.partialmethod >>>>>> - https://docs.python.org/3/library/functools.html#partial-objects >>>>>> >>>>>> > partial Objects¶ >>>>>> > partial objects are callable objects created by partial(). They >>>>>> have three read-only attributes: >>>>>> > >>>>>> > partial.func >>>>>> > A callable object or function. Calls to the partial object will be >>>>>> forwarded to func with new arguments and keywords. >>>>>> > >>>>>> > partial.args >>>>>> > The leftmost positional arguments that will be prepended to the >>>>>> positional arguments provided to a partial object call. >>>>>> > >>>>>> > partial.keywords >>>>>> > The keyword arguments that will be supplied when the partial object >>>>>> is called. >>>>>> >>>>>> > partial objects are like function objects in that they are >>>>>> callable, weak referencable, and can have attributes. There are some >>>>>> important differences. For instance, the __name__ and __doc__ attributes >>>>>> are not created automatically. Also, partial objects defined in classes >>>>>> behave like static methods and do not transform into bound methods during >>>>>> instance attribute look-up. >>>>>> >>>>>> >>>>>> - https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html >>>>>> - >>>>>> https://www.sphinx-doc.org/en/master/_modules/sphinx/ext/autodoc.html >>>>>> : 18 references to __qualname__, >>>>>> >>>>>> >>>>>> https://github.com/sphinx-doc/sphinx/blob/5.x/sphinx/util/inspect.py#L49-L66 >>>>>> : >>>>>> >>>>>> ```python >>>>>> def unwrap_all(obj: Any, *, stop: Optional[Callable] = None) -> Any: >>>>>> """ >>>>>> Get an original object from wrapped object (unwrapping partials, >>>>>> wrapped >>>>>> functions, and other decorators). >>>>>> """ >>>>>> while True: >>>>>> if stop and stop(obj): >>>>>> return obj >>>>>> elif ispartial(obj): >>>>>> obj = obj.func >>>>>> elif inspect.isroutine(obj) and hasattr(obj, '__wrapped__'): >>>>>> obj = obj.__wrapped__ # type: ignore >>>>>> elif isclassmethod(obj): >>>>>> obj = obj.__func__ >>>>>> elif isstaticmethod(obj): >>>>>> obj = obj.__func__ >>>>>> else: >>>>>> return obj >>>>>> ``` >>>>>> >>>>>> From >>>>>> https://github.com/sphinx-doc/sphinx/blob/5.x/sphinx/util/inspect.py#L173-L186 >>>>>> : >>>>>> >>>>>> ```python >>>>>> def unpartial(obj: Any) -> Any: >>>>>> """Get an original object from partial object. >>>>>> This returns given object itself if not partial. >>>>>> """ >>>>>> while ispartial(obj): >>>>>> obj = obj.func >>>>>> >>>>>> return obj >>>>>> >>>>>> >>>>>> def ispartial(obj: Any) -> bool: >>>>>> """Check if the object is partial.""" >>>>>> return isinstance(obj, (partial, partialmethod)) >>>>>> ``` >>>>>> >>>>>> - >>>>>> https://github.com/sphinx-doc/sphinx/issues/4826#issuecomment-808699254 >>>>>> >>>>>> >>>>>> https://docs.python.org/3/library/stdtypes.html#definition.__name__ >>>>>> >>>>>> >>>>>> https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy >>>>>> > Callable types > User defined functions does list both __name__ and >>>>>> __qualname__ >>>>>> >>>>>> Is there a non-performance regressive way to proxy attr access to >>>>>> __name__ of the partially curried (?) function? >>>>>> >>>>>> From "PEP 3155 – Qualified name for classes and functions" >>>>>> https://peps.python.org/pep-3155/#limitations : >>>>>> >>>>>> > ### Limitations >>>>>> > With nested functions (and classes defined inside functions), the >>>>>> dotted path will not be walkable programmatically as a function’s >>>>>> namespace >>>>>> is not available from the outside. It will still be more helpful to the >>>>>> human reader than the bare __name__. >>>>>> > >>>>>> > As the __name__ attribute, the __qualname__ attribute is computed >>>>>> statically and it will not automatically follow rebinding. >>>>>> >>>>>> From >>>>>> https://wrapt.readthedocs.io/en/latest/wrappers.html#proxy-object-attributes >>>>>> : >>>>>> >>>>>> > Proxy Object Attributes >>>>>> > When an attempt is made to access an attribute from the proxy, the >>>>>> same named attribute would in normal circumstances be accessed from the >>>>>> wrapped object. When updating an attributes value, or deleting the >>>>>> attribute, that change will also be reflected in the wrapped object. >>>>>> >>>>>> From https://docs.python.org/3/library/weakref.html#weakref.proxy : >>>>>> >>>>>> > weakref.proxy(object[, callback])¶ >>>>>> > Return a proxy to object which uses a weak reference. This supports >>>>>> use of the proxy in most contexts instead of requiring the explicit >>>>>> dereferencing used with weak reference objects. The returned object will >>>>>> have a type of either ProxyType or CallableProxyType, depending on >>>>>> whether >>>>>> object is callable. Proxy objects are not hashable regardless of the >>>>>> referent; this avoids a number of problems related to their fundamentally >>>>>> mutable nature, and prevent their use as dictionary keys. callback is the >>>>>> same as the parameter of the same name to the ref() function. >>>>>> >>>>>> On Tue, Aug 30, 2022, 1:14 AM Charles Machalow <csm10...@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> 1: There are cases where one may need the __name__/__qualname__ of a >>>>>>> given callable. If someone uses partial to create a new callable, there >>>>>>> is >>>>>>> no __name__/__qualname__ given. In my particular case, I'm logging what >>>>>>> callback function is passed to a different function... if someone uses >>>>>>> partial, there is no __name__/__qualname__ which leads to a current >>>>>>> traceback... of course i can work around it but still was an odd case >>>>>>> to me. >>>>>>> >>>>>>> Per the docs on functools.partial: >>>>>>> "Return a new partial object which when called will behave like func >>>>>>> called with the positional arguments args and keyword arguments >>>>>>> keywords" >>>>>>> ... which made me initially think that in order to behave like the >>>>>>> passed in function: it should have __name__ and __qualname__... like the >>>>>>> func did. >>>>>>> >>>>>>> 2: I would say have both __qualname__ and __name__. Both could be >>>>>>> based off of __name__/__qualname__ of the passed in func. >>>>>>> >>>>>>> 3: This would be more difficult since you would have to >>>>>>> disassemble the lambda to figure out the called method (or methods)... >>>>>>> We >>>>>>> can table the lambda discussion for the purpose of this idea. I recall >>>>>>> that >>>>>>> typically it is preferred to use partial over lambdas, so this could be >>>>>>> an >>>>>>> additional functionality/benefit of using partial over lambda. >>>>>>> >>>>>>> Notes: >>>>>>> ... __name__ being something like partial(foo, "x") would be fine >>>>>>> with me... I just feel as though something should be there. >>>>>>> >>>>>>> - Charlie Scott Machalow >>>>>>> >>>>>>> >>>>>>> On Mon, Aug 29, 2022 at 9:56 PM Paul Bryan <pbr...@anode.ca> wrote: >>>>>>> >>>>>>>> +0 >>>>>>>> >>>>>>>> Questions: >>>>>>>> >>>>>>>> 1. What's the use case for partial having __name__? >>>>>>>> 2. Does this imply it should have __qualname__ as well? >>>>>>>> 3. What name would be given to (an inherently anonymous) lambda? >>>>>>>> >>>>>>>> Notes: >>>>>>>> >>>>>>>> 1. I would prefer __name__ to be more qualifying like its repr >>>>>>>> (e.g. partial(foo, "x") → "<partial foo>") >>>>>>>> >>>>>>>> >>>>>>>> On Mon, 2022-08-29 at 21:31 -0700, Charles Machalow wrote: >>>>>>>> >>>>>>>> Hey folks, >>>>>>>> >>>>>>>> I propose adding __name__ to functools.partial. >>>>>>>> >>>>>>>> >>> get_name = functools.partial(input, "name: ") >>>>>>>> >>> get_name() >>>>>>>> name: hi >>>>>>>> 'hi' >>>>>>>> >>> get_name.__name__ >>>>>>>> Traceback (most recent call last): >>>>>>>> File "<stdin>", line 1, in <module> >>>>>>>> AttributeError: 'functools.partial' object has no attribute >>>>>>>> '__name__' >>>>>>>> >>> get_name.func >>>>>>>> <built-in function input> >>>>>>>> >>> get_name.func.__name__ >>>>>>>> 'input' >>>>>>>> >>>>>>>> We could set __name__ based off of partial.func.__name__ or we >>>>>>>> could try to set it to something like 'partial calling >>>>>>>> func.__name__' >>>>>>>> >>>>>>>> If the callable doesn't have a name, we could fall back to a None >>>>>>>> __name__ or set it to something generic. >>>>>>>> >>>>>>>> Even lambdas have __name__ set: >>>>>>>> >>>>>>>> >>> l = lambda: input('name: ') >>>>>>>> >>> l.__name__ >>>>>>>> '<lambda>' >>>>>>>> >>>>>>>> This proposal makes __name__ on partial objects more useful than >>>>>>>> the current behavior of __name__ on lambda objects as well. We could >>>>>>>> port >>>>>>>> over similar functionality to lambda if we'd like. >>>>>>>> >>>>>>>> - Charlie Scott Machalow >>>>>>>> _______________________________________________ >>>>>>>> Python-ideas mailing list -- python-ideas@python.org >>>>>>>> To unsubscribe send an email to python-ideas-le...@python.org >>>>>>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/ >>>>>>>> Message archived at >>>>>>>> https://mail.python.org/archives/list/python-ideas@python.org/message/WK3FO357ORPVAD3XRUBRH6IHIYSPS3G2/ >>>>>>>> Code of Conduct: http://python.org/psf/codeofconduct/ >>>>>>>> >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>> Python-ideas mailing list -- python-ideas@python.org >>>>>>> To unsubscribe send an email to python-ideas-le...@python.org >>>>>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/ >>>>>>> Message archived at >>>>>>> https://mail.python.org/archives/list/python-ideas@python.org/message/ONAEBCIEJ4DJNWUNWE2ESJ6SBB4O7O6W/ >>>>>>> Code of Conduct: http://python.org/psf/codeofconduct/ >>>>>>> >>>>>> _______________________________________________ >>>> Python-ideas mailing list -- python-ideas@python.org >>>> To unsubscribe send an email to python-ideas-le...@python.org >>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/ >>>> Message archived at >>>> https://mail.python.org/archives/list/python-ideas@python.org/message/YGARINTBW6W32V7YELNEX4VPD7YMPFMR/ >>>> Code of Conduct: http://python.org/psf/codeofconduct/ >>>> >>>
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/YOBWOBCWQQQDWTKSY3XGYNXNZP7MAFUQ/ Code of Conduct: http://python.org/psf/codeofconduct/