Open philipstarkey opened 10 years ago
Original comment by Chris Billington (Bitbucket: cbillington, GitHub: chrisjbillington).
Original comment by Chris Billington (Bitbucket: cbillington, GitHub: chrisjbillington).
Original comment by Chris Billington (Bitbucket: cbillington, GitHub: chrisjbillington).
Original report (archived issue) by Chris Billington (Bitbucket: cbillington, GitHub: chrisjbillington).
Unlike
labscript_devices
, we don't require a unit conversions class to be in a file with the same name as the class within it. And you can have multiple unit conversion classes within a file, in fact I wrote some today. This is good, unit conversion classes can be small and we don't want a proliferation files when related things could be in a file together.So that means that
unitconversions.__init__.py
goes out and doesimport *
from everything, to make sure it gets all the conversion classes.This can have unfortunate side effects, like when you import a single unit conversion class, you unwittingly import them all (this can be a problem if you have line-in-the-sand style reloading of modules, and accidentally put these modules on the wrong side of the line. This isn't just me making up issues, it happened today to me!)
It also pollutes the namespace of
unitconversions.__init__.py
with all the global variables from the files in which unit conversions are defined.What we should do instead is have labscript store the full, qualified class name of the unit conversion class that is used. So that's the fully qualified module name and class name (eg:
labscript_utils.unitconversions.myconversionmodule.MyConversionClass
), the same way that thepickle
module stores what class you're using, so it can import it and instantiate one on unpickling, regardless of whether that class has been imported.A function in
unitconversions.__init__.py
should then be provided that will go and find the relevant class (which can be anywhere in the Python search path), and return it to the caller. This function should happily import the required modules every time it is called, but mostly this will just do nothing because the module will already be insys.modules
and so it will be returned without the code being run. However if aModuleWatcher
has in the meantime unloaded a module due to it changing, it will be re-executed, and the caller will get the brand, shiny new class.When users want a unit conversion class, they will import it directly from wherever it is. When BLACS wants a unit conversion class, it should call that function to get the class by name.
This will not be backward compatible, there is no easy way to make it backward compatible without defeating the benefits completely. So it will be a major version bump and changes in other code will have to have corresponding bumps in their dependency checks.
This helps us further along the path of 'don't run code that isn't yours'. We started with having literally everything in
labscript.py
, but as we branch out to more users and devices, we shouldn't be just executing all code everywhere, just what we need. Otherwise users are subject to the import dependencies and possible crashes of code that is not theirs and they aren't using.