diff --git a/gnssanalysis/solution_types.py b/gnssanalysis/solution_types.py index 7d7987c..e661e76 100644 --- a/gnssanalysis/solution_types.py +++ b/gnssanalysis/solution_types.py @@ -5,6 +5,7 @@ # Abstract base class. Leverages above Immutable metaclass to prevent its (effectively) constants, from being modified. +# Note that this doesn't prevent everything. For example, the contents of a list can still be changed. class SolutionType(metaclass=EnumMetaProperties): name: str long_name: str @@ -86,7 +87,7 @@ class UNK(SolutionType): long_name = "unknown solution type" -class SolutionTypes: +class SolutionTypes(metaclass=EnumMetaProperties): """ Defines valid solution type identifiers specified for use in the IGS long product filename convention v2: https://files.igs.org/pub/resource/guidelines/Guidelines_For_Long_Product_Filenames_in_the_IGS_v2.0.pdf @@ -94,6 +95,9 @@ class SolutionTypes: Also see here for information on session lengths of products pubished by IGS: https://igs.org/products/#about """ + def __init__(self): + raise Exception("This is intended to act akin to an enum. Don't instantiate it.") + FIN = FIN # Final products NRT = NRT # Near-Real Time (between ULT and RTS) PRD = PRD # Predicted products diff --git a/tests/test_solution_type.py b/tests/test_solution_type.py new file mode 100644 index 0000000..80b87f1 --- /dev/null +++ b/tests/test_solution_type.py @@ -0,0 +1,51 @@ +import unittest + +from gnssanalysis.solution_types import SolutionType, SolutionTypes + + +class TestSp3(unittest.TestCase): + def test_shortname_to_solution_type(self): + self.assertEqual(SolutionTypes.from_name("ULT"), SolutionTypes.ULT) + self.assertEqual(SolutionTypes.from_name("RAP"), SolutionTypes.RAP) + self.assertEqual(SolutionTypes.from_name("UNK"), SolutionTypes.UNK) + # AssertRaises can be used either as a context manager, or by breaking out the function arguments. + # Note we're not *calling* the function, we're passing the function *so it can be called* by the handler. + self.assertRaises(ValueError, SolutionTypes.from_name, name="noo") + self.assertRaises(ValueError, SolutionTypes.from_name, name="rapid") + self.assertRaises(ValueError, SolutionTypes.from_name, name="") + self.assertRaises(ValueError, SolutionTypes.from_name, name=" ") + + def test_immutability(self): + def update_base_attribute(): + SolutionType.name = "someNewValue" + + # Note that *contents* of a list can still be modified, despite the more general + # protections provided by the metaclass + + def update_enum_attribute_new(): + SolutionTypes.ULT.name = "someBogusValue" + + self.assertRaises(AttributeError, update_base_attribute) + self.assertRaises(AttributeError, update_enum_attribute_new) + + def instantiate_solution_generic(): + SolutionType() + + def instantiate_solution_specific(): + SolutionTypes.RAP() + + def instantiate_solution_helper(): + SolutionTypes() + + self.assertRaises(Exception, instantiate_solution_generic) + self.assertRaises(Exception, instantiate_solution_specific) + self.assertRaises(Exception, instantiate_solution_helper) + + def test_equality(self): + self.assertEqual(SolutionTypes.RAP, SolutionTypes.RAP, "References to same solution type class should be equal") + self.assertEqual( + SolutionTypes.from_name("RAP"), + SolutionTypes.from_name("rap"), + "from_name should give equal results each time, also regardless of case of input", + ) + self.assertNotEqual(SolutionTypes.RAP, SolutionTypes.UNK, "Non-matching solution types should be unequal")