After more discussions elsewhere [1], I noticed another problem with the dynamic completion table from python.el. Each call to the completion table requires communication with the inferior process. If called frequently enough, the comint input filters can get confused, and some garbage gets printed to the shell. If the inferior is running over Tramp, the problem gets amplified. Now, this is not likely to cause much trouble when calling `completion-at-point' manually, but it is a problem with any of continuously-updating completion UIs like Company or Corfu. To alleviate this, the completion-at-point function could implement some sort of caching. The difficult question is when to invalidate the cache. I've attached one possiblility as a draft patch. If the approach seems reasonable, then I'll format it properly. As a side effect, the patch also solves the original issue described in this ticket. Please let me know what you think. [1] https://github.com/oantolin/orderless/issues/79