attrs icon indicating copy to clipboard operation
attrs copied to clipboard

eval-less implementation, preliminary to browser support

Open glyph opened this issue 9 years ago • 19 comments

On some browser-python runtimes, eval() is either catastrophically slow (brython, skulpt) or completely unavailable (pyj(ama)s, batavia). Since attrs is The Library You Should Absolutely Use No Matter What™, it would be nice if it had an affordance to support those runtimes.

glyph avatar Sep 10 '16 00:09 glyph

We don’t use eval! ✨ 😜

I guess exec is evil too?

hynek avatar Sep 10 '16 06:09 hynek

Oh. It probably should use eval :).

glyph avatar Sep 10 '16 12:09 glyph

But yes, exec has exactly the same limitations.

glyph avatar Sep 10 '16 12:09 glyph

See #87.

glyph avatar Sep 10 '16 12:09 glyph

This might be an interesting technical challenge. But how do we go about it operationally?

  • how to separate the eval code from the fallbacks?
  • how to test the fallbacks?

Guarding sections of code with a flag from _compat would get messy quickly I think.

Tinche avatar Sep 10 '16 21:09 Tinche

@Tinche First - we don't need to do all of those in the same PR :).

glyph avatar Sep 11 '16 01:09 glyph

how to separate the eval code from the fallbacks?

They should just be in totally separate functions. Not supporting eval efficiently is a reasonable thing for a Python runtime to do given certain constraints; but everybody can support returning a higher-order function, so we just have two ways to construct the __init__.

glyph avatar Sep 11 '16 01:09 glyph

how to test the fallbacks?

This doesn't seem hard to me; just set a flag and run all the same unit tests to ensure the behavior is the same.

glyph avatar Sep 11 '16 01:09 glyph

This doesn't seem hard to me; just set a flag and run all the same unit tests to ensure the behavior is the same.

Ideally we could test using one of the runtimes you enumerated. Or monkeypatch eval to blow up when called, but that might break other libs like pytest?

Tinche avatar Sep 11 '16 12:09 Tinche

Ideally we could test using one of the runtimes you enumerated. Or monkeypatch eval to blow up when called, but that might break other libs like pytest?

For testing purposes, we can have a private API that explicitly selects the init-creation mode; @attr._s_but_with_no_eval, as a strawman example.

glyph avatar Sep 12 '16 00:09 glyph

What's the alternative to using eval/exec? For CPython and pypy, we could emit bytecode directly, but that also doesn't support every python implementation out there (pyston).

perkinslr avatar Oct 10 '16 01:10 perkinslr

What's the alternative to using eval/exec?

Calling setattr.

glyph avatar Oct 10 '16 21:10 glyph

Here's another use case for eval-less class creation: building classes from configuration such as swagger/openapi. Because the spec might come from an untrusted source, eval is ill-advised.

reece avatar Apr 17 '17 20:04 reece

Because the spec might come from an untrusted source

If this is the case, then the swagger loader ought to be properly parsing and sanitizing everything (transforming everything into valid identifiers, for example). If the inputs are in the appropriate format, then eval should be just as safe as any other construction mechanism.

glyph avatar Apr 18 '17 02:04 glyph

Just bumped into this issue - our environment doesn't allow either eval or compile. Is there any way we can use this package without either of those functions being required?

tyteen4a03 avatar Nov 24 '19 01:11 tyteen4a03

Not at this time. That should be possible once we have pluggable method builders but there’s sadly no timeline.

hynek avatar Nov 24 '19 16:11 hynek

@tyteen4a03 I am super curious—what environment is this?

glyph avatar Nov 30 '19 22:11 glyph

Not at liberty to say unfortunately, but we do have good reasons for this.

tyteen4a03 avatar Dec 01 '19 00:12 tyteen4a03

@tyteen4a03 Understandable — independent of any reason, any interest in submitting a PR? :)

glyph avatar Feb 18 '20 00:02 glyph