Skip to content

Remove feature flags#316

Open
rwb27 wants to merge 14 commits intomainfrom
remove-feature-flags
Open

Remove feature flags#316
rwb27 wants to merge 14 commits intomainfrom
remove-feature-flags

Conversation

@rwb27
Copy link
Copy Markdown
Collaborator

@rwb27 rwb27 commented Apr 21, 2026

This removes the global FEATURE_FLAGS in favour of per-class settings. This should be much safer. We may in the future want a mechanism to check that the feature is enabled everywhere, but for things like property validation, I think per-class settings are fine.

Things to do before merge:

  • Add tests for Thing._class_settings
  • Decide if that's the best name
  • Add test for BaseDescriptor.owning_class
  • Use BaseDescriptor.owning_class in other places to deduplicate code

OFM Feature Branch: v3-labthings-validate-properties-on-set

rwb27 added 5 commits April 16, 2026 23:32
This adds a class variable to give the Thing settings.

This is overwritten by a descriptor in __init_subclass__ to make it read-only.
This does a few things to remove the need for FEATURE_FLAGS:

* BaseDescriptor gains a property `owning_class`
* Thing gains a class attribute `_class_settings` which is a `TypedDict`
* The class settings typed dict is moved to its own module, and getter functions are defined to define default values etc.
* I moved some exceptions out of `base_descriptor` and into `exceptions`. In the end I only needed them from `base_descriptor` but I've left them in `exceptions` as it would be good to have them centralised.
This fixes example code and adds a note that class settings are intended to be set only once, at definition time.
This filters warnings correctly and removes tests for FEATURE_FLAGS
which is now removed.
@barecheck
Copy link
Copy Markdown

barecheck Bot commented Apr 21, 2026

Barecheck - Code coverage report

Total: 96.7%

Your code coverage diff: 0.06% ▴

Uncovered files and lines
FileLines
src/labthings_fastapi/base_descriptor.py184, 198-199
src/labthings_fastapi/properties.py463, 481, 561, 859, 863, 898-901, 973, 996, 1395
src/labthings_fastapi/thing.py286, 306, 358-360, 481

rwb27 added 7 commits April 21, 2026 18:57
Currently, this checks for `validate_properties_on_set` - as more keys are added, we should include them in testing.

There are explicit tests in `test_thing_class_settings` as well as tests in the context of property set operations in `test_property`.

I fixed a couple of minor things (error messages etc.) as a result of testing.
This uses and tests the `owning_class` property to deduplicate code and give helpful errors.

It introduces a new exception specifically for the case where a class is garbage collected. This is unlikely, but now tested.
Rather than rely on `__init_subclass__` ensuring the settings dictionary exists (though it may still be empty),
we now use a function that is robust to a missing dictionary.

This should work much better with e.g. mixin classes where `__init_subclass__` will not get called.
Previously, I was using the settings on the class where properties were defined. This could lead to different behaviour between properties on the same object, if some properties are inherited from a base class or mixin.
I've swapped `type(obj)` for `obj.__class__` as it can be mocked.

I've updated test code (mostly mocking) to avoid confusion.
The import error message changed slightly, now the test should work with current and new versions.
@rwb27
Copy link
Copy Markdown
Collaborator Author

rwb27 commented Apr 22, 2026

This now works and could be merged. Dealing with Thing._class_settings is not as straightforward as I initially thought, because you need to be careful about whether you take the settings from the "owning class" of a descriptor (i.e. the class where it's defined, possibly a base class) or the class of a Thing instance (i.e. the child class). The latter means all properties on an object are consistent, so that is what we do here.

I think this is clear and consistent, and safer than defining global feature flags. However, it does mean that a descriptor defined on a base class could operate differently on two derived classes. The child classes don't mutate the base class, but they do have their own settings. We may want to consider checking _class_settings for consistency when making subclasses with their own settings.

I think this is a reasonable solution. I'm open to discussion of whether it's the right solution - I will try not to fall too far into being wedded to sunk costs...

@rwb27 rwb27 marked this pull request as ready for review April 22, 2026 09:11
@rwb27 rwb27 force-pushed the remove-feature-flags branch from b732e91 to 7a66580 Compare April 22, 2026 09:14
Now that we read settings from the final class, it's less helpful to check
the key is set on every base class.

We now check the key is present when it's read. This may result in
more warnings, but fewer spurious ones.

Repeated warnings can be suppressed in the usual way.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant