HNHacker News
TopNewBestAskShowJobs

hauntsaninja

405 karma · joined May 9, 2020

submissionscomments
hauntsaninja··on Show HN: Git bayesect – Bayesian Git bisection for non-deterministic bugs
I don't yet know a better way to do this than using a threshold!

I think if you assume perf is normally distributed, you can still get some of the math to work out. But I will need to think more about this... if I ever choose this adventure, I'll post an update on https://github.com/hauntsaninja/git_bayesect/issues/25

(I really enjoy how many generalisations there are of this problem :-) )

hauntsaninja··on Show HN: Git bayesect – Bayesian Git bisection for non-deterministic bugs
Note that "pick the commit with best expected information gain" in git_bayesect isn't optimal even in the no overhead regime. I provide a counterexample in the writeup, which implies ajb's heuristic is also not optimal. I don't see a tractable way to compute the optimal policy.

One idea: if you always spend time testing equal to your constant overhead, I think you're guaranteed to be not more than 2x off optimal.

(and agreed with ajb on "just use ccache" in practice!)

hauntsaninja··on Show HN: Git bayesect – Bayesian Git bisection for non-deterministic bugs
Yep, you can run bayesect to an arbitrary confidence level.

This script in the repo https://github.com/hauntsaninja/git_bayesect/blob/main/scrip... will show you that a) the confidence level is calibrated, b) how quickly you get to that confidence level (on average, p50 and p95)

For the failure rates you describe, calibration.py shows that you should see much higher accuracy at 300 tests

hauntsaninja··on Show HN: Git bayesect – Bayesian Git bisection for non-deterministic bugs
That sounds right. `git_bayesect` currently uses `--first-parent`, so I think belden's use case should work, but I haven't tested it much on complicated git histories.
hauntsaninja··on Show HN: Git bayesect – Bayesian Git bisection for non-deterministic bugs
Yes! It will show you the posterior probability as a single commit starts to become more likely. In addition, running `git bayesect status` will show you all posterior probabilities
hauntsaninja··on Show HN: Git bayesect – Bayesian Git bisection for non-deterministic bugs
Yay, I had fun with it too!

IIUC the way you'd do that right now is just repeatedly recording the individual observations on a single commit, which effectively gives it a probability + the number of trials to do the Beta update. I don't yet have a CLI entrypoint to record a batch observation of (probability, num_trials), but it would be easy to add one

But ofc part of the magic is that git_bayesect's commit selection tells you how to be maximally sample efficient, so you'd only want to do a batch record if your test has high constant overhead

hauntsaninja··on Show HN: Git bayesect – Bayesian Git bisection for non-deterministic bugs
git bisect works great for tracking down regressions, but relies on the bug presenting deterministically. But what if the bug is non-deterministic? Or worse, your behaviour was always non-deterministic, but something has changed, e.g. your tests went from somewhat flaky to very flaky.

In addition to the repo linked in the title, I also wrote up a little bit of the math behind it here: https://hauntsaninja.github.io/git_bayesect.html

hauntsaninja··on Claude Opus 4.6
Reasoning effort is denominated in tokens, not time, so no difference beyond slowness at heavy load

(I work at OpenAI)

hauntsaninja··on How uv got so fast
Yes, uv skipping this step is a one time significant hit to start up time. E.g. if you're building a Dockerfile I'd recommend setting `--compile-bytecode` / `UV_COMPILE_BYTECODE`
hauntsaninja··on Announcing the Beta release of ty
Unknown has the exact same type system semantics as Any.

Unknown is a pyright specific term for inferred Any that is used as the basis for enabling additional diagnostics prohibiting gradual typing.

Notably, this is quite different from TypeScript’s unknown, which is type safe.

hauntsaninja··on Announcing the Beta release of ty
I’ve added ecosystem regression checks to every Python type checker and typeshed via https://github.com/hauntsaninja/mypy_primer. This helped a tonne with preventing unintended or overly burdensome regressions in mypy, so glad to hear upgrades are less of an Event for you
hauntsaninja··on Announcing the Beta release of ty
The conformance test suite is currently mostly focused on “what does an explicit type annotation mean”

A shared spec for this is important because if you write a Python library, you don’t want to have to write a different set of types for each Python type checker

Here are some things the spec has nothing to say about:

Inference

You don’t want to annotate every expression in your program. Type checkers have a lot of leeway here and this makes a huge difference to what it feels like to use a type checker.

For instance, mypy will complain about the following, but pyright will not (because it infers the types of unannotated collections as having Any):

  x = []
  x.append(1)
  x[0] + "oops"
The spec has nothing to say about this.

Diagnostics

The spec has very little to say about what a type checker should do with all the information it has. Should it complain about unreachable code? Should it complain if you did `if foo` instead of `if foo()` because it’s always true? The line between type checker and linter is murky. Decisions here have nothing to do with “what does this annotation mean”, so are mostly out of scope from the spec.

Configuration

This makes a huge difference when adapting huge codebases to different levels of type checking. Also the defaults really matter, which can be tricky when Python type checkers serve so many different audiences.

Other things the spec doesn’t say anything about: error messages quality, editor integration, speed, long tail of UX issues, implementation of new type system features, plugins, type system extensions or special casing

And then of course there are things we would like to spec but haven’t yet!

hauntsaninja··on Announcing the Beta release of ty
Mentioned this in another comment, but the spec conformance suite is not representative of the things users care about (nor is it meant to be).

The spec mostly concerns itself with the semantics of annotations, not diagnostics or inference. I don't really recommend using it as the basis for choosing a type checker.

(I was on the Python Typing Council and helped put together the spec, the conformance test suite, etc)

hauntsaninja··on Announcing the Beta release of ty
Note: while spec conformance is important, I don't recommend using it as the basis for choosing a type checker. It is not representative of the things that most users actually care about (and is not meant to be).

(I was on the Python Typing Council and helped put together the spec, the conformance test suite, etc)

hauntsaninja··on Python developers are embracing type hints
pyright will accept this. mypy should accept this when using --allow-redefinition-new as well
hauntsaninja··on OpenAI Progress
text-davinci-001 is just not GPT-3 in any real sense

(I work at OpenAI, I helped build this page and helped train text-davinci-001)

hauntsaninja··on Ty: A fast Python type checker and language server
Note that `uvx mypy` may give you inaccurate timings on macOS. The antivirus in macOS goes a little crazy the first time it executes a mypyc compiled program.
hauntsaninja··on C stdlib isn't threadsafe and even safe Rust didn't save us
We had so many of these issues that we ended up LD_PRELOAD-ing patch getenv / setenv / putenv
hauntsaninja··on Uv's killer feature is making ad-hoc environments easy
Yeah, that's not exactly the problematic situation... but the good news is I improved the Python's error message for this in 3.13. See https://docs.python.org/3/whatsnew/3.13.html#improved-error-...
hauntsaninja··on PEP 760: No more bare excepts
You don't need to use pytz, you can use the following on all Python 3: tz_UTC = datetime.timezone.utc
hauntsaninja··on Python types have an expectations problem
Lean heavier on a mypy config file. Make heavy use of per-module configuration, in particular, setting per-module ignore_errors = true for modules you’re not yet ready to type check.

See https://mypy.readthedocs.io/en/stable/existing_code.html for some more advice.

hauntsaninja··on Use `Python -m Pip`
In Python 3.11, you can use the "-P" flag or the "PYTHONSAFEPATH" environment variable to avoid adding cwd to sys.path

https://docs.python.org/3.11/whatsnew/3.11.html#summary-rele...

hauntsaninja··on You Should Compile Your Python and Here’s Why
You can use numpy just fine. Unlike Cython, mypyc doesn’t give you a way of accessing numpy’s C API (because you’re basically just writing Python code).
hauntsaninja··on You Should Compile Your Python and Here’s Why
mypy compiles itself with mypyc, for about a 3.5-4x speed up. black very recently started shipping mypyc compiled binaries, for about a 2x speed up (iirc).
hauntsaninja··on You Should Compile Your Python and Here’s Why
mypyc has escape hatches, e.g. casting to Any is a common trick.
hauntsaninja··on Easily handle CLI operation via Python instead of regular Bash programs
I wrote a similar tool a while back. My solution for this was to statically analyse the input to discover unused names. The cool part of doing transformations statically is that you're able to see the exact Python code you'd run without running it, e.g. `pyp --explain x[:5]`. https://github.com/hauntsaninja/pyp
hauntsaninja··on Easily handle CLI operation via Python instead of regular Bash programs
I wrote a similar tool a while back that lets you create your own "magic" variables. I use `f` all the time! https://github.com/hauntsaninja/pyp#pyp-lets-you-configure-y...
hauntsaninja··on Exhaustiveness Checking with Mypy
Python's static type system can express what you describe using TypeVars or overloads. The issue is that `int pow(int, int)` is fundamentally incorrect. If the exponent is a negative integer, the return type would need to be float.

As evidenced by your comment, most people forget about negative exponents. The vast majority of usage is positive exponents; people expect an int back when they do `pow(2, 2)` and returning a Union or float would result in annoying false positives.

hauntsaninja··on Show HN: Pyp – Easily, magically, run Python at the shell
Thanks to everyone who checked pyp out!

Not sure if this comment will ever get seen, but I just added the ability to configure pyp with statically analysed Python, so it's easy to define your own functions, import aliases, or use libraries like pipetools to make your life easier! More details at https://github.com/hauntsaninja/pyp#pyp-is-configurable

hauntsaninja··on Show HN: Pyp – Easily, magically, run Python at the shell
There are a number of possible options! And remember you can always pipe pyp to pyp. Here are some ideas, in order of what came to mind, where the operation is incrementing.

  pyp 'lines[lines.index("start") + 1:]' | pyp 'lines[:lines.index("end")]' | pyp 'int(x) + 1'
  
  pyp 'start = lines.index("start"); end = lines.index("end", start); map(lambda x: int(x) + 1, lines[start + 1:end])'
  
  pyp 'dropwhile(lambda x: x != "start", lines)' | pyp 'lines[1:]' | pyp 'takewhile(lambda x: x != "end", lines)' | pyp 'int(x) + 1'
  
  pyp 'map(lambda x: int(x) + 1, takewhile(lambda x: x != "end", islice(dropwhile(lambda x: x != "start", lines), 1, None)))'
  
  pyp -b 'cond = False' 'if cond and x == "end": break' 'if cond: print(int(x) + 1)' 'if x == "start": cond = True'
Page 1 of 2Next →