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

ycecream: a no dependency. Pythonic fork of IceCream #58

Closed
salabim opened this issue Feb 26, 2021 · 10 comments
Closed

ycecream: a no dependency. Pythonic fork of IceCream #58

salabim opened this issue Feb 26, 2021 · 10 comments

Comments

@salabim
Copy link

salabim commented Feb 26, 2021

I like the IceCream package very much, but there were several reasons why I made a fork.
This solves also a number of issues raised here.

The ycecream package can be found here: https://github.com/salabim/ycecream and can be installed directly from PyPI.

Here are the main differences:

  • ycecream can't colourize the output (a nice feature of IceCream)
  • ycecream runs only on Python 3.6 and higher. (IceCream runs even on Python 2.7).
  • ycecream uses y as the standard interface, whereas IceCream uses ic. For compatibility, ycecream also supports ic.
  • yceceam has no dependencies. IceCream on the other hand has many (asttoken, colorize, pyglets, ...).
  • ycecream is just one .py file, whereas IceCream consists of a number of .py files. That makes it possible to use ycecream without even (pip) installing it. Just copy ycecream.py to your work directory.
  • ycecream can be used as a decorator of a function or method showing the enter and/or exit event as well as the duration (useful for simple benchmarks)
  • ycecream can output directly to a callable (like IceCream), but also an open file (e.g. sys.stdout) or a file given by the name (strr of Path)
  • ycecream uses a different PEP8 compatible API to customize (rather than IceCream's configureOutput method)
  • ycecream time showing can be controlled independently from context showing
  • ycecream can optionally show a delta (time since start of the program)
  • ycecream does not sort dicts by default. This behaviour can be controlled with the sort_dict parameter. (This is implemented by including the pprint 3.8 source code)
  • ycecream uses pytest for the test scripts rather than IceCream's unittest script.
@alexmojaki
Copy link
Collaborator

I like the IceCream package very much, but there were several reasons why I made a fork.
This solves also a number of issues raised here.

If an issue was raised here, why not make a PR solving that issue? If there was no issue here, why not make one? Seems like all of these features could be in icecream:

  • ycecream can be used as a decorator of a function or method showing the enter and/or exit event as well as the duration (useful for simple benchmarks)
  • ycecream can output directly to a callable (like IceCream), but also an open file (e.g. sys.stdout) or a file given by the name (strr of Path)
  • ycecream time showing can be controlled independently from context showing
  • ycecream can optionally show a delta (time since start of the program)
  • ycecream uses pytest for the test scripts rather than IceCream's unittest script.

As for this:

  • yceceam has no dependencies. IceCream on the other hand has many (asttoken, colorize, pyglets, ...).
  • ycecream is just one .py file, whereas IceCream consists of a number of .py files. That makes it possible to use ycecream without even (pip) installing it. Just copy ycecream.py to your work directory.

Perhaps this should be done in an automated manner with a tool like https://pypi.org/project/stickytape/ . Is that what https://github.com/salabim/ycecream/blob/main/install%20ycecream%20from%20github.py is? What will you do when there are changes to executing, asttokens, or icecream?

@salabim
Copy link
Author

salabim commented Feb 26, 2021

I started with this project as I didn't like the API (not Pythonic) and wanted a single source package. That didn't seemed to be just a PR for IceCream, so I started my own fork.

Feel free to use whatever you want from my package to make IceCream more useful (particularly decorators!).

With respect to changes in the underlying packages: these will of course not automatically be incorporated. On the other hand, ycecream will not suffer from changes in the API's of these packages (although that's quite unlikely).

The file 'install ycecream from github.py' is just another way
to install ycecream.py directly in site-packages, wthout PyPI.

@gruns
Copy link
Owner

gruns commented Feb 26, 2021

ycecream can be used as a decorator of a function or method showing the enter and/or exit event as well as the duration (useful for simple benchmarks)

this is definitely something we want. see #32

design discussion, and later pull requests, welcome there!

ycecream uses a different PEP8 compatible API to customize (rather than IceCream's configureOutput method)

ya. as icecream has grown, so too have the number of options

it's now clunky to pack so many params into ic.configureOutput(). the configuration API in general needs a simplification and overhaul

ycecream can output directly to a callable (like IceCream), but also an open file (e.g. sys.stdout) or a file given by the name (strr of Path)

this is certainly possible with ic.configureOutput(outputFunction=yourFunctionHere)

it could be useful to have those 'batteries' included and if you hand outputFunction a file object or string it 'does the right thing'. for example, could rename outputFunction to output and accept values:

  1. a function: current implementation which invokes the provided function with icecream's output
  2. a string: open the file with the given string filepath and write to it
  3. file object: write to the file object using the file object API, eg fobj.write()

@alexmojaki https://pypi.org/project/stickytape/ is neat. i, personally, havent seen it used by other projects, though

think it'd be worth using stickytape to build a single icecream.py file for download and inclusion?

at this time, my gut says no. this is the first time someone has requested a single file version of icecream

@alexmojaki
Copy link
Collaborator

alexmojaki commented Feb 26, 2021

I only found stickytape just now after a quick google. Seems like there's other possibilities for single file packaging.

You can see places it's used here, the most significant being https://github.com/doyensec/inql with 704 stars where it looks like it works very well.

Overall it's not clear to me why this kind of thing is important. In the case of InQL it looks like you need a single file to load as an extension for other software. For icecream, I don't know what significant advantage there is. I've seen this kind of thing requested once before here, and again it's not clear if it was necessary.

I think the most sensible path would be to:

  1. Integrate as much code as possible (within reason) into the base repo. icecream is popular and well known and contributions here will reach the most people and do the most good. Making ycecream equally well known will be very hard. Even if it happened, many will still use icecream anyway.
  2. Keep the separate fork for differences that are not easily integrated, like breaking compatibility changes. But if it's very similar to the base repo because of the previous point, updates made in the base will be easy to merge into the fork.
  3. Automate the process of building a single file with stickytape or something else. Maybe have it in the base repo, maybe not. Then updates in dependencies can still be used automatically. New Python versions tend to break asttokens and executing, so some strategy for keeping these up to date is necessary.

I've done something similar before. I know having your own codebase and complete control is easier and more fun. But I still contributed as much as I could to the original repo before I had to make a fork, and it was worth it. And in general, code in my fork was not pulled back into the base by anyone. That doesn't happen easily or naturally.

@salabim You can of course do whatever you like, but I think it's a bit sad that someone clearly so interested in working on this project would keep all their contributions separate and isolated.

@jkyeung
Copy link

jkyeung commented Mar 31, 2021

@gruns - I am sure I am in a very tiny minority, but I would be interested in a single-file icecream.py.

My reason for wanting a single file is related to the reason I don't just go ahead and use ycecream.py (since I actually am not particularly interested in the color features). I would love to be able to use icecream with an obscure and esoteric implementation of Python that is stuck at 2.7 and does not have pip or any other easy installers.

@alexmojaki
Copy link
Collaborator

obscure and esoteric implementation of Python

What implementation? The magic behind icecream and ycecream uses a lot of CPython implementation details. PyPy imitates these details which is why it works there, but there's no guarantees for all Pythons.

Download https://github.com/alexmojaki/executing/blob/master/executing/executing.py (a single file!) and then try running this code (from a file, not a shell):

import ast
import executing
import inspect

frame = inspect.currentframe()
print(ast.dump(executing.Source.for_frame(frame).executing(frame).node))

The expected output is something like this:

Call(func=Attribute(value=Call(func=Attribute(value=Attribute(value=Name(id='executing', ctx=Load()), attr='Source', ctx=Load()), attr='for_frame', ctx=Load()), args=[Name(id='frame', ctx=Load())], keywords=[], starargs=None, kwargs=None), attr='executing', ctx=Load()), args=[Name(id='frame', ctx=Load())], keywords=[], starargs=None, kwargs=None)

If you just get an exception or None, icecream isn't going to work.

@alexmojaki
Copy link
Collaborator

Otherwise you can try https://github.com/zestyping/q . It comes in a single file and is slightly less magical so it might have a better chance of working outside of CPython.

@jkyeung
Copy link

jkyeung commented Mar 31, 2021

obscure and esoteric implementation of Python

What implementation? The magic behind icecream and ycecream uses a lot of CPython implementation details. PyPy imitates these details which is why it works there, but there's no guarantees for all Pythons.

It's iSeriesPython, running on IBM i, built primarily from the source for (I believe) CPython 2.7.1. It's still implemented in C and still recognizably a CPython.

Download https://github.com/alexmojaki/executing/blob/master/executing/executing.py (a single file!) and then try running this code (from a file, not a shell):

import ast
import executing
import inspect

frame = inspect.currentframe()
print(ast.dump(executing.Source.for_frame(frame).executing(frame).node))

The expected output is something like this:

Call(func=Attribute(value=Call(func=Attribute(value=Attribute(value=Name(id='executing', ctx=Load()), attr='Source', ctx=Load()), attr='for_frame', ctx=Load()), args=[Name(id='frame', ctx=Load())], keywords=[], starargs=None, kwargs=None), attr='executing', ctx=Load()), args=[Name(id='frame', ctx=Load())], keywords=[], starargs=None, kwargs=None)

I got exactly that output string, so at least that part of the puzzle fits.

@jkyeung
Copy link

jkyeung commented Apr 3, 2021

Originally posted by @salabim in #67 (comment)

Ycvecream is now available under Python 2.7.
No dependencies and the full functionality! Give it a try.

Excellent! I tried it and it works!

You got through the backport quicker than I expected.

@gruns
Copy link
Owner

gruns commented Apr 17, 2021

closing

future readers of this issue: please open tickets/PRs for any features you'd like to see in icecream -- like from ycream or elsewhere!

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

No branches or pull requests

4 participants