Skip to content

Conversation

@bblommers
Copy link
Contributor

@bblommers bblommers commented Jan 28, 2026

Motivation

This PR adds typehints to some utilities (utils/strings.py and utils/threads.py) and explicitly verifies the correctness using mypy.

The original intention was to only add types to the most common methods, like to_str and start_thread - but adding types to the entire file wasn't that much more effort, that's why I went all out.

Some logic has been moved around - I'll add some inline comments to explain what happened, and why this is (IMHO) acceptable.

The (single) test that we had for FuncThreads has also been reworked and moved to a dedicated testfile, with some additional tests for good measure.

Not sure who actually owns these utilities! @alexrashed I've tagged you as the resident Python guru, but feel free to re-assign if you think someone else is more suitable 🙂

@bblommers bblommers added this to the Playground milestone Jan 28, 2026
@bblommers bblommers added semver: patch Non-breaking changes which can be included in patch releases docs: skip Pull request does not require documentation changes notes: skip Pull request does not have to be mentioned in the release notes labels Jan 28, 2026
@github-actions
Copy link

github-actions bot commented Jan 28, 2026

Test Results - Preflight, Unit

23 088 tests  +4   21 229 ✅ +4   6m 11s ⏱️ -15s
     1 suites ±0    1 859 💤 ±0 
     1 files   ±0        0 ❌ ±0 

Results for commit b66207d. ± Comparison against base commit 08f7836.

This pull request removes 1 and adds 5 tests. Note that renamed tests count towards both.
tests.unit.test_common.TestCommon ‑ test_cleanup_threads_and_processes_calls_shutdown_hooks
tests.unit.utils.test_threads.TestThreads ‑ test_cleanup_threads_and_processes_calls_shutdown_hooks
tests.unit.utils.test_threads.TestThreads.TestStartThread ‑ test_start_thread_returns_a_func_thread
tests.unit.utils.test_threads.TestThreads.TestStartThread ‑ test_start_thread_with_custom_name
tests.unit.utils.test_threads.TestThreads.TestStartWorkerThread ‑ test_start_worker_thread_returns_a_func_thread
tests.unit.utils.test_threads.TestThreads.TestStartWorkerThread ‑ test_start_worker_thread_with_custom_name

♻️ This comment has been updated with latest results.

from localstack.utils.objects import recurse_object

if isinstance(value, (dict, list)):
if isinstance(value, str):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here is unchanged - just flipped to test the smallest type first. This was necessary because ComplexType includes the type object, and strings are a type of object. Ergo: isinstance("x", ComplexType) would resolve to True, and that's not what we want.

Comment on lines -58 to -59
if argspec.varkw or "_thread" in (argspec.args or []) + (argspec.kwonlyargs or []):
kwargs["_thread"] = self
Copy link
Contributor Author

@bblommers bblommers Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This.. thing was only used in one place, but that usage has now been refactored (see related PR), so this wart is no longer necessary.

@bblommers bblommers force-pushed the typing-utils-strings-threads branch 2 times, most recently from 5a7f998 to 36bbc81 Compare January 28, 2026 12:34
@github-actions
Copy link

github-actions bot commented Jan 28, 2026

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 57m 1s ⏱️ - 1m 10s
5 176 tests ±0  4 788 ✅ ±0  388 💤 ±0  0 ❌ ±0 
5 178 runs  ±0  4 788 ✅ ±0  390 💤 ±0  0 ❌ ±0 

Results for commit b66207d. ± Comparison against base commit 08f7836.

♻️ This comment has been updated with latest results.

@bblommers bblommers force-pushed the typing-utils-strings-threads branch 2 times, most recently from a563d1f to fcde7b7 Compare January 28, 2026 13:03
if argspec.varkw or "_thread" in (argspec.args or []) + (argspec.kwonlyargs or []):
kwargs["_thread"] = self
kwargs = {} # type: ignore[var-annotated]
result = self.func(self.params, **kwargs)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we always pass self.params, usage currently looks like this:

    def run_install(*args):
        assert args == (None,)

    start_worker_thread(run_install)

In an ideal world, we would not need to define any arguments:

def run_install():
    pass

start_worker_thread(run_install)

and only pass in any parameters if configured:

def run_install(arg1, arg2):
    pass

start_worker_thread(run_install, params=("arg1", "arg2"))

However, this would include a refactoring of all the usages of this pattern across the codebase, so I'm just leaving this as-is for now.



def convert_to_printable_chars(value: list | dict | str) -> str:
def convert_to_printable_chars(value: "str | ComplexType") -> "ComplexType":
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used ComplexType here just because it's an existing type that accurately describes the possibilities.

For reference, this is what ComplexType looks like:

ComplexType = list | dict | object

This does need more attention later on, but that's not a rabbit hole I'm willing to dive into right now 🙂

@bblommers bblommers force-pushed the typing-utils-strings-threads branch from fcde7b7 to b66207d Compare January 29, 2026 07:30
@github-actions
Copy link

Test Results (amd64) - Acceptance

7 tests  ±0   5 ✅ ±0   2m 59s ⏱️ -2s
1 suites ±0   2 💤 ±0 
1 files   ±0   0 ❌ ±0 

Results for commit b66207d. ± Comparison against base commit 08f7836.

@github-actions
Copy link

Test Results (amd64) - Integration, Bootstrap

    5 files  ±0      5 suites  ±0   2h 35m 41s ⏱️ - 1m 35s
5 597 tests ±0  5 039 ✅ ±0  558 💤 ±0  0 ❌ ±0 
5 603 runs  ±0  5 039 ✅ ±0  564 💤 ±0  0 ❌ ±0 

Results for commit b66207d. ± Comparison against base commit 08f7836.

@bblommers bblommers requested a review from alexrashed January 29, 2026 08:43
@bblommers bblommers marked this pull request as ready for review January 29, 2026 08:43
Copy link
Member

@alexrashed alexrashed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup of what's some really historical code! 💯
The changes are looking great, some nice cleanups in there and the changes should be functional equivalent besides the changes you outlined (and which should be safe as well).
I think it might be a good idea to quickly verify that these changes really don't cause any issues in our downstream project, but then this should be good to go! 🚀 :shipit:

@bblommers
Copy link
Contributor Author

Thanks again for the review @alexrashed - can confirm that this does not cause any issues downstream 👍

@bblommers bblommers merged commit 59e81ce into main Jan 30, 2026
47 checks passed
@bblommers bblommers deleted the typing-utils-strings-threads branch January 30, 2026 10:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs: skip Pull request does not require documentation changes notes: skip Pull request does not have to be mentioned in the release notes semver: patch Non-breaking changes which can be included in patch releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants