Hacker News new | past | comments | ask | show | jobs | submit login

looks really cool! congrats, seems like a lot of work went into this, and code generation is always fun.

i do have some feedback about the readme though...

maybe i'm not the intended audience, but the examples didn't work great for me - the readme just shows the code without the inputs/outputs, so you kind of have to guess what it does. ("show me your tables, not your flowcharts" etc.)

i also think you should add some more basic examples / common tasks, e.g. converting AOS to SOA:

  [{'a': 5,  'b': 'foo'},
   {'a': 10, 'b': 'bar'} ]
    
  c.fun['stuff'](data) # look how concise!
  
  {'a': [5,     10   ],
   'b': ['foo', 'bar']}
and build up to more complex stuff from there, to help readers get a feel for the library.

and i think the examples should be a bit higher up in the readme – ofc wanting to describe how cool the implementation is is natural :) but honestly, when i'm looking at a library like this, i want to be able to make a quick assessment if might be useful for me - the implementation is kind of secondary in most cases.

now, despite what i wrote above, i'd love to hear some stuff about the implementation :) as someone who also wrote a library that does runtime python codegen, what's your approach to that?




thank you very much for the feedback! this is very valuable! :)

Regarding the README, I'll improve it within the next few days.

As for the approach, the main assumption was that everything is simple as long as you deal with expressions only, so I've introduced every expression I needed as a conversion object (each able to generate the code within the context).

Exceptions are custom code generating parts (e.g. aggregate, reducers) and the part where I break down piped conversions into a series of statements in the top level converter.

Another tricky piece was to support parametrization - e.g. c.input_arg here - https://convtools.readthedocs.io/en/latest/cheatsheet.html#c... So it was necessary to make every conversion know about every inner dependency it has, to make all dependencies pop up, to know function signatures & parameters needed to be passed during internal generation of functions.


sounds interesting, i'll have a look at the code when i have time. i've mostly done compiler stuff like this with the "one function with a huge switch on the expression type" approach, curious to see what the more OOP-ish way looks like.

btw: wow, that cheatsheet is exactly what i had in mind on my first comment, that's the kind of stuff i'd like in a readme! maybe a few excerpts with a link to the whole thing.

some more remarks if you're interested:

---

in that cheatsheet it'd be cool to also show the generated code for each example, maybe in a collapsible box or sth – in that context the actual semantics of a convtools expression are useful to know.

---

have you thought about some magic syntactic sugar? the current approach is kind of visually heavy, since you're basically writing an AST by hand. with some __dunder__ hacking you could easily (?) add a "magic" api like

  from convtools.magic import magic as m
  
  c.item('key') ->
  m['key']
  
  c.call_method('foo', ...) ->
  m.meth.foo(...)
  
  c.call_function('bar', ...)  ->
  m.func.bar(...)
or something similar. it might be a bit too magical for some tastes, but if you're constructing a python expression, it kind of makes sense to use python syntax for that


oh, thanks, I'll add links to cheatsheet and quickstart pages to the README, it really makes sense!

As for the magic-stuff, I was contemplating designing the API with this approach, but I changed my mind because it would be difficult to tell which python expressions are evaluated at the moment of a conversion definition AND which in the compiled code.

However if we imagine this "magic" API, then it could be even closer to normal python code:

  m["key"].some_method(...)
which would resolve everything under the hood.

===

as for the collapsable generated code examples -- I've jotted down :)


> it would be difficult to tell which python expressions are evaluated at the moment of a conversion definition AND which in the compiled code

this is ofc a valid concern in any metaprogramming situation. has this been a problem in your experience? i'm guessing e.g. generating a conversion based on a list of fields is a thing someone might do, but it feels like a minority usecase (at least to me, someone with no actual experience with using the library :p)


Re: whether it's been a problem in my experience -- sort of - yes

So now I'm doing my best to observe: PEP-20 the 2nd commandment with the hope that I'm not violating the 1st commandment badly :) https://www.python.org/dev/peps/pep-0020/

Also I see another upside of this no-magic syntax in that it is distinctive -- there's no way to mix up convtools-related code with any other python code.


In re: the "magic", it seems to me that you could use a mock object and get the required info from it.


In terms of the implementation, it's kind of trivial to implement the "magic", but it would be both confusing and inconsistent, see below.

e.g. imagine a case where you'd want to call datetime.strptime, partially initializing it at the moment of conversion definition. at the moment it is:

  c.call_func(
      datetime.strptime,
      c.item("updated"),
      "%Y-%m-%d"
  )
but it's unclear to me how would the "magic" approach deal with the case above.


Replace your current namespace with a mock object? You can eval or exec code with any dictionary-flavored object, and mocks can imitate dicts.

edit: no, you can't in Python 3..

I'll try to have a closer look later today.


What do you think about a DSL alternative?


We would need to bring the whole python into it :/


looks really cool -- will evaluate when the API is stable -- would hate to adopt only to have it change from under me




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: