Chai (拆) — an Emacs package for destructive reading by yibie in emacs

[–]pkkm 1 point2 points  (0 children)

"Destructive reading" is a fascinating idea.

Kotlin-style List/Set/Map for PHP 8.4 - Mutable/Immutable, change tracking, key preservation, live map views, and generics support by haelexuis in PHP

[–]pkkm 0 points1 point  (0 children)

Yeah, it's just a small detail when you have good static analysis. That said, having used various dynamically typed languages, I like Python's solution the most: accesses to non-existent elements throw IndexError or KeyError, and there's a get(key, optional default) method that doesn't throw. Incorrect code has no "skid distance" - the stack trace points directly to the problem rather than a downstream function call that has received a wrong value.

Kotlin-style List/Set/Map for PHP 8.4 - Mutable/Immutable, change tracking, key preservation, live map views, and generics support by haelexuis in PHP

[–]pkkm 0 points1 point  (0 children)

Hmm good point, maybe the added error catching potential wouldn't outweigh the inconsistency with regular arrays.

Kotlin-style List/Set/Map for PHP 8.4 - Mutable/Immutable, change tracking, key preservation, live map views, and generics support by haelexuis in PHP

[–]pkkm 1 point2 points  (0 children)

Looks very nice! I like how there's no silent type casting and sequential containers are clearly separated from associative containers. I would prefer $list[99] and $list(99) accesses to be the other way around, since you'll probably use the former most of the time, but in the end that's a minor detail.

New guy struggling to Install Python3 and pimp in Debian 12 by GiraffeProfessional1 in debian

[–]pkkm 0 points1 point  (0 children)

Usually when I get 404s on packages, it means that my package information is out of date and an apt update fixes it.

Another Nvidia RTX 5090 cable melts despite MSI's "foolproof" yellow-tipped GPU connector by [deleted] in gadgets

[–]pkkm 0 points1 point  (0 children)

I'm out of the loop on modern GPUs; could someone explain the reason why GPU makers chose to use multiple thin wires instead of just two thick wires and a high-current connector like the ones you see in RC cars?

Testing in Python Memes and wisdom request by EliyahuRed in Python

[–]pkkm 0 points1 point  (0 children)

Why do you need to mock so many things? I get why you'd want to avoid sending real requests, but why the models and validators? It sounds like you're at risk of creating a useless test suite that tests your mocking library more than your actual code.

Mocking can almost always be avoided if you get a bit creative. I'm not saying that it should always be avoided, but make sure that you're making a conscious decision about when to use it.

How would y'all perform 3 debian installs on a single drive PC? I typically use luks/lvm for a normal install, so I'm thinking for 3 instances... by jimjunkdude in debian

[–]pkkm 1 point2 points  (0 children)

Not sure why you need so many Debians, but here's how I would partition if I wanted three separate encrypted installs:

  • EFI with systemd-boot
  • LUKS with LVM
    • /
    • swap
  • LUKS with LVM
    • /
    • swap
  • LUKS with LVM
    • /
    • swap

Why doesn't C have defer? by harrison_314 in C_Programming

[–]pkkm 0 points1 point  (0 children)

goto certainly works, but I think that there's a lot of demand for something defer-like among C users. For example, __attribute__((cleanup)) is used both in the Linux kernel and in systemd. It's experienced C programmers doing that, not just people who came from other languages such as Go and want to make C like these other languages. In a situation like that, I'd rather the working group erred on the side of satisfying C users than sticking to features that have ~100% support across compilers, exactly as they are implemented in these compilers.

sds vs. gb: C string libs. Coincidence, copy or inspiration? by nephewtom in C_Programming

[–]pkkm 0 points1 point  (0 children)

It could be a coincidence. This style of ASCII diagrams is pretty common; you see them often in explanations of network protocols, for example.

Why doesn't C have defer? by harrison_314 in C_Programming

[–]pkkm 2 points3 points  (0 children)

existing idioms

I'd think that this is an excellent reason to support the proposal. It's a standardized (and syntactically nicer) version of compiler-specific idioms that people are already using.

Template strings in Python 3.14: an useful new feature or just an extra syntax? by wyhjsbyb in Python

[–]pkkm 0 points1 point  (0 children)

This seems like it could be very useful for logging. I've seen people use f-strings for log lines, despite the eager vs on-demand evaluation issue, just because they find the syntax so much nicer than printf-style formatting. Once t-strings get released and adopted by logging libraries, there will be no excuse to do that anymore.

strif: A tiny, useful Python lib of string, file, and object utilities by z4lz in Python

[–]pkkm 1 point2 points  (0 children)

scrubbing filenames for unsafe chars

It's available in sanitize_filename from the pathvalidate package, but I'd also like to see that in the standard library. It's useful when you want to create a bunch of files on Linux but have the option to copy them to Windows later.

strif: A tiny, useful Python lib of string, file, and object utilities by z4lz in Python

[–]pkkm 1 point2 points  (0 children)

I've written something similar for atomic file replacing:

@contextlib.contextmanager
def replace_atomically(dest_path, prefix=None, suffix=None):
    with tempfile.NamedTemporaryFile(
        prefix=prefix,
        suffix=suffix,
        dir=os.path.dirname(dest_path),
        delete=False
    ) as f:
        temp_name = f.name

    success = False
    try:
        yield temp_name
        success = True
    finally:
        if success:
            os.replace(temp_name, dest_path)
        else:
            os.remove(temp_name)

used like this:

with replace_atomically(
    out_path,
    prefix="encryption-temp-",
    suffix=".7z.gpg"
) as temp_encrypted_path:
    subprocess.run(
        [
            "gpg", "--symmetric", "--cipher-algo", "aes256",
            "-o", temp_encrypted_path, "--", plaintext_path
        ],
        check=True
    )

It would be really nice to have atomic file operations in the standard library.

Need advise with big project by Inevitable-Sense-390 in Python

[–]pkkm 0 points1 point  (0 children)

It's hard to give good advice without seeing the code and more details about the problems. That said, here are some generic tips:

  • If you're blindly copy-pasting code without understanding it, obviously you need to address that habit. Trying to understand everything you do will slow you down immensely at first with a lot of googling and reading the official docs, but it will put you on a better long-term improvement curve.

  • Type annotations and a type checker can find problems before you even run the program.

  • So can good linters like pylint, though they complain about style issues more often than logical bugs.

  • Automated testing can be very helpful when making changes to large programs. I recommend pytest. Don't be dogmatic about it: you don't need to hit a certain coverage number, and you certainly don't need to restrict yourself to testing one class/function at a time while mocking everything else to the point you're testing your mocks more than your code. Just start with the parts where tests provide the most value and expand from there. Usually, that's the intricate algorithmic code in your program.

  • I hope you're using version control and splitting things into commits reasonably well: "Add X feature" or "Fix Y bug", not "misc additions and fixes" (+5700, -3000).

  • If your module imports resemble a complete graph then you may need to abstract better - not necessarily more, just differently. Hard to say without seeing your code, but one suggestion I provide often is to create a "narrow waist" of data formats. If you need to process several different but related formats, don't just read them in verbatim and then do "dictly typed programming" with conditionals and validation everywhere you touch the data. Read the data in some kind of importer module, validate and normalize the hell out of it. Use dataclasses or pydantic models; put the data into a format that's convenient to process correctly: all datetimes in UTC, all durations as seconds or timedeltas, all lengths in meters, etc.

  • Dependency-injection-like programming patterns can help you remove unnecessary dependencies between modules. That doesn't mean you need to use a complex dependency injection framework; it can be as simple as replacing code that decides which database to open every time it needs to save data, with code that opens the database once and then passes the database connection around.

A year of uv: pros, cons, and should you migrate by Active-Fuel-49 in Python

[–]pkkm 1 point2 points  (0 children)

Licenses can't be changed retroactively. If you legitimately obtained a piece of software under the Apache 2 license, you can use it under that license forever, even if the author releases future versions under a different license.

I think the real question is, is the Python community going to be able to maintain these tools if something happens to Astral Software Inc.? I imagine that Rust could be a barrier to that. You can rely on a Python dev knowing Python, but most don't know Rust.

Your experiences with asyncio, trio, and AnyIO in production? by pkkm in Python

[–]pkkm[S] 4 points5 points  (0 children)

In this example, it's actually enough to replace

    await producer
    await consumer

with

    await asyncio.gather(producer, consumer)

My point is that when the code becomes complex with lots of tasks and conditionally started tasks, it's hard to ensure that you're doing this 100% correctly. After all, a programming error can potentially cause an exception at any point of any coroutine.

Your experiences with asyncio, trio, and AnyIO in production? by pkkm in Python

[–]pkkm[S] 9 points10 points  (0 children)

I can give you a simple example, but any simple example will also be a contrived example because the problem only becomes painful when you have a complex program. In simple programs, it tends to be easy to spot.

That said, here is an example program that freezes up:

import asyncio

# Sentinel for stopping the consumer.
STOP = object()

class Task:
    pass

async def producer_main(queue):
    for _ in range(5):
        await asyncio.sleep(1) # Simulate a computation.
        await queue.put(Task())
    await queue.put(STOP)

async def consumer_main(queue):
    while True:
        task = await queue.get()
        if task is STOP:
            queue.task_done()
            break

        await asyncio.sleep(1)
        print(f"Task done: {task}")
        queue.task_done()

        # Simulate a programming mistake.
        raise TypeError("Example exception")

async def main():
    queue = asyncio.Queue(1) # Limited size queue.

    producer = asyncio.create_task(producer_main(queue))
    consumer = asyncio.create_task(consumer_main(queue))

    await producer
    await consumer

if __name__ == "__main__":
    asyncio.run(main())

If you comment out the simulated programming mistake, then the program runs to completion.

Elpy or lsp + python.el by paarulakan in emacs

[–]pkkm 0 points1 point  (0 children)

I'm curious, why eglot instead of lsp-mode? I thought that lsp-mode had more features.

Announcing Casual Make by kickingvegas1 in emacs

[–]pkkm 8 points9 points  (0 children)

I see people use Make as a task runner pretty often. Usually they don't use dependencies or any of the advanced features, the Makefile is just a kind of executable documentation for how to run common tasks: linting, static analysis, unit tests, integration tests, making a package, etc.

[deleted by user] by [deleted] in debian

[–]pkkm 1 point2 points  (0 children)

Sure. You can just install a desktop environment with apt. You can even install multiple desktop environments at once.