HackerTrans
TopNewTrendsCommentsPastAskShowJobs

yeti-sh

no profile record

Submissions

Show HN: Jeeves – A Pythonic Alternative to GNU Make

jeeves.sh
55 points·by yeti-sh·3 ปีที่แล้ว·84 comments

Show HN: Use Python docstrings as exception messages

github.com
7 points·by yeti-sh·3 ปีที่แล้ว·0 comments

comments

yeti-sh
·3 ปีที่แล้ว·discuss
The exception is raised if the command returns a non-zero error code. If it returns a zero error code then the return value of, say,

    compose.up()
contains the command's stdout.

In addition stdout can be redirected to a file, or to another command, or to a callable, ­— which will be called for chunks of stdout while the command is in operation.
yeti-sh
·3 ปีที่แล้ว·discuss
No it does not, in fact; errors or warnings will pop up as an unhandled exception and print:

- command actually executed,

- snippet of stdout

- and snippet of stderr.

They can be handled using standard exception techniques.
yeti-sh
·3 ปีที่แล้ว·discuss
To change the wording in the title of this post would be improper in view of multitude of comments referring to this title. I will consider rebranding this.
yeti-sh
·3 ปีที่แล้ว·discuss
I feel the majority still uses qwerty keyboards; I assumed that when choosing the name and the shortcut for the tool.

Experiences differ, and de gustibus on est disputandum; in my bubble, virtualenv is a must-have for Python development.

I have multiple Python projects, they run different versions of Python itself and its libraries, and for many of them Docker would be an overkill; so it is hard for me to imagine my routine without virtual environments.

I employ pyenv to manage them but venv is a venv.
yeti-sh
·3 ปีที่แล้ว·discuss
I see. The P key isn't that ergonomically placed though; and again, one will have to do this time and again for each virtual environment, right?

Why not use native Python methods, namely endpoints, instead, and automate this away?
yeti-sh
·3 ปีที่แล้ว·discuss
Regarding sync checks which Make has as a built-in feature, I am not yet positive how to best implement it. Maybe something like

    @pre(file_name=_file_is_in_sync)
    def build(file_name: Path):
        ...
I believe such libraries do exist even, but I haven't yet researched the topic; if jeeves proves to be useful for the simplest use case then it will make sense to expand its scope.
yeti-sh
·3 ปีที่แล้ว·discuss
> argh & a symlink in /usr/bin.

- Is putting a symlink to one of your project directories, probably residing in $HOME, to /usr/bin/ a good practice?

- As an alternative one can put a symlink into ~/bin; but what if you have multiple different projects?

- And they can have different jeeves commands and different plugins installed. For instance, `j lint` implementations in different projects are work on are completely different.

Because these are different projects.

Rather, I prefer to have jeeves automatically create the executable command in each virtual env, and its behavior in different virtual envs will be different.
yeti-sh
·3 ปีที่แล้ว·discuss
There are a lot of projects, both commercial and OSS, which have a Makefile for linting, version releases, etc, — and never use its dependency graph feature; or, their usage is so superficial that implementing it, say,

- via direct function calls in Python code,

- or using Typer callback functions

…is easy.

There are potential approaches worth exploring (annotations, decorators, …). I might come up with a list of options with syntax examples and ask for community's thoughts about it, — but at this point jeeves, as an MVP, is already useful for me and a few people I work with, and that motivated me to share it with the community.
yeti-sh
·3 ปีที่แล้ว·discuss
That's right; Google also published a similar package named `fire`, I used it a lot.

> just `python your_file.py`

That's actually one of the points.

    j lint
is shorter than

    python scripts.py lint
and the letter `j` is what the index finger of your right hand is pointing to on the keyboard. There is usually a tactile bump on that key. It is something you can type very quickly. You can also install shell completion to improve the experience further.

Ergonomics matters.
yeti-sh
·3 ปีที่แล้ว·discuss
An example from the top of my head:

    compose = sh.docker.compose.bake('-f', 'deploy/dev.yml')
    …
    compose.down()
    …
    compose.up('--force-recreate', '-d')
I feel this is a major improvement on top of Makefiles + shell commands in them. Nice API _matters_; it is ergonomics and therefore productivity.

You can specify `_out=rich.print` and it will work but AFAIK it won't scrape ASCII terminal formatting characters.

I had to fix these characters in my `sh` based scripts but do not consider that as a big deal.
yeti-sh
·3 ปีที่แล้ว·discuss
Saying 'GNU Make' particularly was an automatism. When I use Make I do use GNU Make specifically. I do not have experience with BSD Make, or other Make dialects.

> did actually do a suitable job of replacing gnu make

The title does not say _a replacement_, it says _an alternative_. I never intended to replace GNU Make; if I said that anywhere — that was a mistake on my part.

> do improve upon those who created unix

I did not intend to improve upon UNIX ideas or philosophy. The improvements I am aiming for are:

- developer experience,

- conciseness and maintainability of the code.

…and these are being addressed for a narrow use case. For that use case, in my experience, Make is very often used.

I argue that within the bounds of this use case, this is an alternative which can be of use to improve productivity and everyday experience.

> I don't really understand the full job make does, so here is something which only does a simpler job which I do understand, and I like python

I classify these assumptions about my understanding or misunderstanding as ad hominem and unprofessional.
yeti-sh
·3 ปีที่แล้ว·discuss
For a Python project, I'd recommend doing this as a dev dependency.

* jeeves is the name of the project which I'm advertising, which converts a Python file to a set of commands; * `j` is the name of executable which aformentioned project exposes; * and `sh` is the library (the correct link to which you have provided) which is an optional dependency of `jeeves` and provides a more convenient interface to calling processes and executing commands from Python than `subprocess.run()`.
yeti-sh
·3 ปีที่แล้ว·discuss
You are right, jeeves doesn't do that. Your example reminds me of how I first learnt to use Make; I built my LaTeX stuff from source when in university.

However, dealing with Python mostly in my time in the industry, I scarcely ever had the need to use these particular features of Make. I used it as a task runner, guilty of that, — and that's what I wanted to reimplement in Python.

Even writing in Rust, everything I have to do is `cargo build`, — there is no need to write Makefiles for building the project.

I will consider changing that wording to set proper expectations, but I still feel that for me "a Pythonic alternative to Make" perfectly conveys the use case I daily employ this thing for.
yeti-sh
·3 ปีที่แล้ว·discuss
You can also install a jeeves plugin with pip. Say,

    pip install jeeves-yeti-pyproject
will provide you with jeeves, a bunch of commands, and a pack of dev dependencies which I personally happen to like and to use in my projects.

I don't believe Make has plugins.
yeti-sh
·3 ปีที่แล้ว·discuss
I looked at pyinvoke before I started jeeves. Roughly, as much as I can recall, there were a few reservations:

- no type hints for docs & validation, I wanted them

- Makefile in its basic form is very concise and doesn't require a @task decorator, I didn't want it either

I didn't need dependency graph much.
yeti-sh
·3 ปีที่แล้ว·discuss
Please elaborate. Do you mean submitting commands via ssh to remote servers from the script?

The way I'd recommend to run shell commands from jeeves is `sh` library. It has features for ssh support: https://sh.readthedocs.io/en/latest/sections/contrib.html#ss...
yeti-sh
·3 ปีที่แล้ว·discuss
I like sh for brevity of its API. I often have to use `_tty_out=False`, but this is easy to fix once and for all commands in a script:

    my_sh = sh.bake(_tty_out=False)
    my_sh.do_whatever()
The way how sh captures output can apparently be altered, say, by providing a callable to _out argument.
yeti-sh
·3 ปีที่แล้ว·discuss
Thanks, will check this out!
yeti-sh
·3 ปีที่แล้ว·discuss
Thanks for the point. I've had to deal with argparse-based code (not finding it very enjoyable) but didn't recognize the resemblance.
yeti-sh
·3 ปีที่แล้ว·discuss
That's right. For projects which only use subset of Make features described by (1) jeeves can be considered an alternative for Make, and I would believe there are quite a few such projects.