443 karma · joined August 11, 2023
You could just as well install it either globally with pixi global, or as a project dependency in a pixi project. In this case, the latter.
> I also have a few shared envs, for quick tests
Fair, I just use temporary directories with pixi projects for that and thus no longer see a point in conda envs for this. It has the added benefit that all my temporary directories are in the same location and easy to get rid of.
> general utils
I would want those to be available at all times, so conda envs aren't fit for that purpose. Instead, I use pixi's global subcommand.
> Poetry for project management.
That limits you to lock files for python dependencies only, unfortunately. In a project relying on browser automation, I would want the browser version to be recorded in the lock file as well. Pixi does that.
---
I still don't really see why you found pixi lacking. It addresses all of your problems, maybe with the exception of globally installing multiple and non-CLI packages. But again, conda isn't any better as you are generally advised not to install stuff into the base env and conda has no other facility for globally installing general utilities.
I've found that there really only are two kinds of packages I want to install: those I want globally (e.g. CLI tools like git, git-annex, DataLad, whatever shell enhancing you want, etc.) and project-specific dependencies (anything required to get going with it on a freshly installed system with the smallest amount of assumptions possible).
The former is sufficiently addressed by `pixi global` and other package managers, the latter by pixi projects. Notably, conda environments are a bad fit for both (not global, not really updatable, not automatically tied to a project, not rebuildable due to missing lock files, ...).
Even if you have all versions as of the time of the last modification to the code, you don't know if the dependency resolution happened at that point in time, or if the environment was set up years prior and never updated.
Nevertheless, this is what you are looking for: https://pypi.org/project/pypi-timemachine/
Iff it must be the conda ecosystem, pixi (https://pixi.sh/latest/) is a much better pick.
But conda-style packages (or anything with install time dependency resolution really) also have the issue of being completely untestable. That makes them unsuitable at least for user-facing package management, if you care about your packages not randomly breaking without warning.
I'd rather see every language converge on a single package manager that implements functional package management, i.e. guix or nix. One can dream...
I've seen a service whose registration form accepted my 64 characters long randomly generated password, but then the login form apparently truncated the password to something smaller, silently, and just said my password was incorrect. I then had to guess what was happening and reset my password to something shorter, which worked. If you must have a stupid password policy at least make it explicit (well, and consistent).
Then someone else can take over, or not, depending on how important it really is to those 150000.
From the perspective of a business, using open source is strictly safer than closed source. With closed source, if the entity owning the code goes bankrupt, increases licensing fees substantially, just axes the project (incidentally what Google is also known for) or looses interest in some other way, you are out of luck. Go find something similar and hope there is a migration path. With open source, the equivalent is the maintainer walking away because they are bored, and you have the code right there to take over, or pay someone else to do so.
> I question the validity of open-sourcing anything for fun unless you design the licence, and more, to enable you to walk away and/or get bored.
Every open source license is already designed so that you can just walk away for whatever reason, e.g. when you are bored.
I wouldn't necessarily call "GlobalScopeForWorker" more clunky than "WorkerGlobalScope", just a bit longer, but also more descriptive.
Using the languages namespacing features might also make it more obvious, e.g. "Worker::GlobalScope" and "Worklet::GlobalScope" or the inverted version "GlobalScope::{Worker,Worklet}".
Looking at it from a functional programming perspective, I also like approaches of the form "GlobalScopeFor({Worker,Worklet})", i.e. a function returning the respective thing.
Naming things is hard, but the possibilities are endless...
Sounds like a good idea, actually. These places being the entire surface of your code that is exposed to the real world. So not unlike what I have been suggesting.
Do you have any particular example in mind that is not superfluous and really can not be exercised by the public API? I have a hard time thinking of any.
If they aren't then you are defending against situations that can never occur. In that case the check seems unnecessary, and I at least wouldn't make it a priority to cover it. Also, those checks are usually simple enough that one can reason about them easily, again making it less of a priority to have tests cover them.
> The other problem is that finding tests that cover everything from the public interfaces can be extremely difficult. Most test suites don't achieve full coverage even of theoretically reachable points in the code.
Yes, testing is hard. That is not a reason to write more detrimental tests though.
Unit testing is fine, if you do it for your public interface. If you are writing a math library then sure, unit test that `add(1, 2) == 3`. But if you just have an internal helper function for that, then think about if you really want to lock its existence and behavior into place, or if that would just hinder future architectural changes.
You can always test the exposed functionality that uses the helper and achieve full coverage of it that way. If you can't, then you have dead code.
Of course this is all a bit more nuanced. Past a certain size it might make sense to e.g. consider one modules interface to be public for the rest of your application and test it. But you can definitely overdo it and testing every single function you write (as I've seen people unironically suggest) is very likely detrimental.
As examples: If you are creating a web API, only test against the exposed public routes of that API, instead of writing tests for internal helpers. If you are creating a GUI application, programmatically exercise the GUI instead of starting your tests halfway into the innards that respond to the GUI buttons.
Tests lock behavior into place, so you should only write tests for behavior that needs to be locked.
There are some simple next steps to go from there:
- notice that you don't have to reset to the main branch, you can put in any branch name
- it doesn't even have to be a branch name, it can be any kind of reference to a commit
- 'git reflog' is useful to find out a reference to a commit you recently were on, that you can then give to reset
- you don't have to use --hard, I personally like using --keep, and sometimes you might want to keep local changes so you don't supply those options at all
- ...
What you already did is what Zambyte suggested you should do. Of course there is diminishing returns at some point, but that point comes way after 'git commit -am $msg && git push'.> However, at present SSHFS does not have any active, regular contributors, and there are a number of known issues (see the bugtracker).
Not that it is unusable or anything, it is still in widespread use, but I'd guess many assume it to be part of openssh and maintained with it, when it isn't.
An interesting alternative might be https://rclone.org/, which can speak SFTP and can mount all (of the many) protocols it speaks.
I am not sure how it could break anything though, unless you are parsing stderr of your script in a subsequent step, which would seem unusual anyway.
set -euxo pipefail
The "u" has basically the same effect as the question mark, but for every variable usage. apt install bar
from a users view is not. It can have a different result depending on what is already installed, or even if all other system state is the same it can change with time.My point is that a package "bar v3.2.1" that depends on "libfoo v1.2.3" needs to be considered a different package than "bar v3.2.1" that depends on "libfoo v1.2.4" or even "libfoo v1.2.3 compiled with -O3 instead of -O2", because the resulting package can behave differently due to the variation.
But as soon as you have that there is no need for install time dependency resolution anymore, since it is all done at build time.
The important part is being able to install two packages in isolation, irrespective of if they represent the same software in different versions or if they are completely unrelated. Apt couldn't install two unrelated packages if they contain files that have the same path, to my knowledge.
As soon as one foregos putting everything into a single filesystem structure (like in FHS, which most distros follow to some extent) the logical conclusion will be to prefix each packages directory with some identifier that meaningfully describes its content (which could be considered an "extended version" of this package). With nix this is a hash of all the inputs that went into the package (its own source code, compiler flags, build settings, dependencies, etc. and recursively the same for all of its dependencies). This means that if the compiler flags of e.g. a five levels deep transitive dependency are changed, then the package that depends on it changes as well, which is only reasonable since its behavior could change.
At that point all dependency resolution has happened at build time and none is required at runtime. Being able to install different versions of the same package is merely a by-product of this approach.
"Functional package management", as implemented in nix and guix, is a much saner approach.
For basically all purposes ansible is imperative.
Since apparently (I try to avoid ansible, so I might be missing something) playbooks are the go-to approach of using ansible this means that most uses of ansible are imperative (in the context of configuring a system), unless you only ever give a system a singular role and then you are probably defining your role in imperative steps.
A system like NixOS on the other hand presents the entirety of a system configuration in a single declarative interface that is applied in one go, while applying such a configuration to a system can be a thought of as an imperative step (although it is usually a singular, unconditional step). So it is declarative at a higher abstraction level.
That's the thing, with NixOS you usually don't have to explicitly setup users and permissions. For most simple services, the entire setup is a single line of code in your NixOS configuration. E.g.
services.uptime-kuma.enable = true;
will make sure that your system is running an uptime-kuma instance, with its own user and all.Some more complex software might require more configuration, but most of the time user and group setup is not part of that.
Given that ansible has neither it can't be much better then what it is. I disagree that that is the right choice though. As it is I see not much more value in ansible than in some sort of SSH over xargs contraption combined with a list of servers. The guarantees they give are the same.
> Do you know every package that should be installed because it comes out of the box in the distro? Do you want to [...]?
No, I don't want to. Thankfully, with NixOS I don't need to, since the pre-installed packages are automatically part of the declared state of my NixOS systems (i.e. I declare the wanted state in the same way in which the defaults are also declared, which makes it easy to merge both).
The irony of which is that it only runs on Google's phones.
You don't expect a random generator to spit out facts, you expect to get random nonsense. But it can be very good at replicating the fitted probability distribution in its output, i.e. generate convincingly coherent language.