qnty 0.0.7__py3-none-any.whl → 0.0.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. qnty/__init__.py +140 -58
  2. qnty/_backup/problem_original.py +1251 -0
  3. qnty/_backup/quantity.py +63 -0
  4. qnty/codegen/cli.py +125 -0
  5. qnty/codegen/generators/data/unit_data.json +8807 -0
  6. qnty/codegen/generators/data_processor.py +345 -0
  7. qnty/codegen/generators/dimensions_gen.py +434 -0
  8. qnty/codegen/generators/doc_generator.py +141 -0
  9. qnty/codegen/generators/out/dimension_mapping.json +974 -0
  10. qnty/codegen/generators/out/dimension_metadata.json +123 -0
  11. qnty/codegen/generators/out/units_metadata.json +223 -0
  12. qnty/codegen/generators/quantities_gen.py +159 -0
  13. qnty/codegen/generators/setters_gen.py +178 -0
  14. qnty/codegen/generators/stubs_gen.py +167 -0
  15. qnty/codegen/generators/units_gen.py +295 -0
  16. qnty/codegen/generators/utils/__init__.py +0 -0
  17. qnty/equations/__init__.py +4 -0
  18. qnty/equations/equation.py +257 -0
  19. qnty/equations/system.py +127 -0
  20. qnty/expressions/__init__.py +61 -0
  21. qnty/expressions/cache.py +94 -0
  22. qnty/expressions/functions.py +96 -0
  23. qnty/expressions/nodes.py +546 -0
  24. qnty/generated/__init__.py +0 -0
  25. qnty/generated/dimensions.py +514 -0
  26. qnty/generated/quantities.py +6003 -0
  27. qnty/generated/quantities.pyi +4192 -0
  28. qnty/generated/setters.py +12210 -0
  29. qnty/generated/units.py +9798 -0
  30. qnty/problem/__init__.py +91 -0
  31. qnty/problem/base.py +142 -0
  32. qnty/problem/composition.py +385 -0
  33. qnty/problem/composition_mixin.py +382 -0
  34. qnty/problem/equations.py +413 -0
  35. qnty/problem/metaclass.py +302 -0
  36. qnty/problem/reconstruction.py +1016 -0
  37. qnty/problem/solving.py +180 -0
  38. qnty/problem/validation.py +64 -0
  39. qnty/problem/variables.py +239 -0
  40. qnty/quantities/__init__.py +6 -0
  41. qnty/quantities/expression_quantity.py +314 -0
  42. qnty/quantities/quantity.py +428 -0
  43. qnty/quantities/typed_quantity.py +215 -0
  44. qnty/solving/__init__.py +0 -0
  45. qnty/solving/manager.py +90 -0
  46. qnty/solving/order.py +355 -0
  47. qnty/solving/solvers/__init__.py +20 -0
  48. qnty/solving/solvers/base.py +92 -0
  49. qnty/solving/solvers/iterative.py +185 -0
  50. qnty/solving/solvers/simultaneous.py +547 -0
  51. qnty/units/__init__.py +0 -0
  52. qnty/{prefixes.py → units/prefixes.py} +54 -33
  53. qnty/{unit.py → units/registry.py} +73 -32
  54. qnty/utils/__init__.py +0 -0
  55. qnty/utils/logging.py +40 -0
  56. qnty/validation/__init__.py +0 -0
  57. qnty/validation/registry.py +0 -0
  58. qnty/validation/rules.py +167 -0
  59. qnty-0.0.9.dist-info/METADATA +199 -0
  60. qnty-0.0.9.dist-info/RECORD +63 -0
  61. qnty/dimension.py +0 -186
  62. qnty/equation.py +0 -216
  63. qnty/expression.py +0 -492
  64. qnty/unit_types/base.py +0 -47
  65. qnty/units.py +0 -8113
  66. qnty/variable.py +0 -263
  67. qnty/variable_types/base.py +0 -58
  68. qnty/variable_types/expression_variable.py +0 -68
  69. qnty/variable_types/typed_variable.py +0 -87
  70. qnty/variables.py +0 -2298
  71. qnty/variables.pyi +0 -6148
  72. qnty-0.0.7.dist-info/METADATA +0 -355
  73. qnty-0.0.7.dist-info/RECORD +0 -19
  74. /qnty/{unit_types → codegen}/__init__.py +0 -0
  75. /qnty/{variable_types → codegen/generators}/__init__.py +0 -0
  76. {qnty-0.0.7.dist-info → qnty-0.0.9.dist-info}/WHEEL +0 -0
@@ -0,0 +1,123 @@
1
+ {
2
+ "total_dimensions": 110,
3
+ "generated_dimensions": [
4
+ "absorbed_dose",
5
+ "acceleration",
6
+ "activation_energy",
7
+ "amount_of_substance",
8
+ "angle_plane",
9
+ "angle_solid",
10
+ "angular_acceleration",
11
+ "angular_momentum",
12
+ "area",
13
+ "area_per_unit_volume",
14
+ "atomic_weight",
15
+ "concentration",
16
+ "dimensionless",
17
+ "dynamic_fluidity",
18
+ "electric_capacitance",
19
+ "electric_charge",
20
+ "electric_current_intensity",
21
+ "electric_dipole_moment",
22
+ "electric_field_strength",
23
+ "electric_inductance",
24
+ "electric_potential",
25
+ "electric_resistance",
26
+ "electrical_conductance",
27
+ "electrical_permittivity",
28
+ "electrical_resistivity",
29
+ "energy_flux",
30
+ "energy_heat_work",
31
+ "energy_per_unit_area",
32
+ "force",
33
+ "force_body",
34
+ "force_per_unit_mass",
35
+ "frequency_voltage_ratio",
36
+ "fuel_consumption",
37
+ "heat_of_combustion",
38
+ "heat_of_fusion",
39
+ "heat_of_vaporization",
40
+ "heat_transfer_coefficient",
41
+ "illuminance",
42
+ "kinetic_energy_of_turbulence",
43
+ "length",
44
+ "linear_mass_density",
45
+ "linear_momentum",
46
+ "luminance_self",
47
+ "luminous_flux",
48
+ "luminous_intensity",
49
+ "magnetic_field",
50
+ "magnetic_flux",
51
+ "magnetic_induction_field_strength",
52
+ "magnetic_moment",
53
+ "magnetic_permeability",
54
+ "magnetomotive_force",
55
+ "mass",
56
+ "mass_density",
57
+ "mass_flow_rate",
58
+ "mass_flux",
59
+ "mass_fraction_of_i",
60
+ "mass_transfer_coefficient",
61
+ "molality_of_solute_i",
62
+ "molar_concentration_by_mass",
63
+ "molar_flow_rate",
64
+ "molar_flux",
65
+ "molar_heat_capacity",
66
+ "molarity_of_i",
67
+ "mole_fraction_of_i",
68
+ "moment_of_inertia",
69
+ "momentum_flow_rate",
70
+ "momentum_flux",
71
+ "normality_of_solution",
72
+ "particle_density",
73
+ "percent",
74
+ "permeability",
75
+ "photon_emission_rate",
76
+ "power_per_unit_mass",
77
+ "power_per_unit_volume",
78
+ "power_thermal_duty",
79
+ "pressure",
80
+ "radiation_dose_equivalent",
81
+ "radiation_exposure",
82
+ "radioactivity",
83
+ "second_moment_of_area",
84
+ "second_radiation_constant_planck",
85
+ "specific_enthalpy",
86
+ "specific_gravity",
87
+ "specific_heat_capacity_constant_pressure",
88
+ "specific_length",
89
+ "specific_surface",
90
+ "specific_volume",
91
+ "stress",
92
+ "surface_mass_density",
93
+ "surface_tension",
94
+ "temperature",
95
+ "thermal_conductivity",
96
+ "time",
97
+ "torque",
98
+ "turbulence_energy_dissipation_rate",
99
+ "velocity_angular",
100
+ "velocity_linear",
101
+ "viscosity_dynamic",
102
+ "viscosity_kinematic",
103
+ "volume",
104
+ "volume_fraction_of_i",
105
+ "volumetric_calorific_heating_value",
106
+ "volumetric_coefficient_of_expansion",
107
+ "volumetric_flow_rate",
108
+ "volumetric_flux",
109
+ "volumetric_mass_flow_rate",
110
+ "wavenumber"
111
+ ],
112
+ "base_dimensions": [
113
+ "LENGTH",
114
+ "MASS",
115
+ "TIME",
116
+ "CURRENT",
117
+ "TEMPERATURE",
118
+ "AMOUNT",
119
+ "LUMINOSITY",
120
+ "DIMENSIONLESS"
121
+ ],
122
+ "signatures_cached": 73
123
+ }
@@ -0,0 +1,223 @@
1
+ {
2
+ "total_units": 871,
3
+ "total_fields": 107,
4
+ "total_dimensions": 107,
5
+ "dimension_constants": [
6
+ "ABSORBED_DOSE",
7
+ "ACCELERATION",
8
+ "ACTIVATION_ENERGY",
9
+ "AMOUNT_OF_SUBSTANCE",
10
+ "ANGLE_PLANE",
11
+ "ANGLE_SOLID",
12
+ "ANGULAR_ACCELERATION",
13
+ "ANGULAR_MOMENTUM",
14
+ "AREA",
15
+ "AREA_PER_UNIT_VOLUME",
16
+ "ATOMIC_WEIGHT",
17
+ "CONCENTRATION",
18
+ "DIMENSIONLESS",
19
+ "DYNAMIC_FLUIDITY",
20
+ "ELECTRICAL_CONDUCTANCE",
21
+ "ELECTRICAL_PERMITTIVITY",
22
+ "ELECTRICAL_RESISTIVITY",
23
+ "ELECTRIC_CAPACITANCE",
24
+ "ELECTRIC_CHARGE",
25
+ "ELECTRIC_CURRENT_INTENSITY",
26
+ "ELECTRIC_DIPOLE_MOMENT",
27
+ "ELECTRIC_FIELD_STRENGTH",
28
+ "ELECTRIC_INDUCTANCE",
29
+ "ELECTRIC_POTENTIAL",
30
+ "ELECTRIC_RESISTANCE",
31
+ "ENERGY_FLUX",
32
+ "ENERGY_HEAT_WORK",
33
+ "ENERGY_PER_UNIT_AREA",
34
+ "FORCE",
35
+ "FORCE_BODY",
36
+ "FORCE_PER_UNIT_MASS",
37
+ "FREQUENCY_VOLTAGE_RATIO",
38
+ "FUEL_CONSUMPTION",
39
+ "HEAT_OF_COMBUSTION",
40
+ "HEAT_OF_FUSION",
41
+ "HEAT_OF_VAPORIZATION",
42
+ "HEAT_TRANSFER_COEFFICIENT",
43
+ "ILLUMINANCE",
44
+ "KINETIC_ENERGY_OF_TURBULENCE",
45
+ "LENGTH",
46
+ "LINEAR_MASS_DENSITY",
47
+ "LINEAR_MOMENTUM",
48
+ "LUMINANCE_SELF",
49
+ "LUMINOUS_FLUX",
50
+ "LUMINOUS_INTENSITY",
51
+ "MAGNETIC_FIELD",
52
+ "MAGNETIC_FLUX",
53
+ "MAGNETIC_INDUCTION_FIELD_STRENGTH",
54
+ "MAGNETIC_MOMENT",
55
+ "MAGNETIC_PERMEABILITY",
56
+ "MAGNETOMOTIVE_FORCE",
57
+ "MASS",
58
+ "MASS_DENSITY",
59
+ "MASS_FLOW_RATE",
60
+ "MASS_FLUX",
61
+ "MASS_FRACTION_OF_I",
62
+ "MASS_TRANSFER_COEFFICIENT",
63
+ "MOLALITY_OF_SOLUTE_I",
64
+ "MOLARITY_OF_I",
65
+ "MOLAR_CONCENTRATION_BY_MASS",
66
+ "MOLAR_FLOW_RATE",
67
+ "MOLAR_FLUX",
68
+ "MOLAR_HEAT_CAPACITY",
69
+ "MOLE_FRACTION_OF_I",
70
+ "MOMENTUM_FLOW_RATE",
71
+ "MOMENTUM_FLUX",
72
+ "MOMENT_OF_INERTIA",
73
+ "NORMALITY_OF_SOLUTION",
74
+ "PARTICLE_DENSITY",
75
+ "PERCENT",
76
+ "PERMEABILITY",
77
+ "PHOTON_EMISSION_RATE",
78
+ "POWER_PER_UNIT_MASS",
79
+ "POWER_PER_UNIT_VOLUME",
80
+ "POWER_THERMAL_DUTY",
81
+ "PRESSURE",
82
+ "RADIATION_DOSE_EQUIVALENT",
83
+ "RADIATION_EXPOSURE",
84
+ "RADIOACTIVITY",
85
+ "SECOND_MOMENT_OF_AREA",
86
+ "SECOND_RADIATION_CONSTANT_PLANCK",
87
+ "SPECIFIC_ENTHALPY",
88
+ "SPECIFIC_GRAVITY",
89
+ "SPECIFIC_HEAT_CAPACITY_CONSTANT_PRESSURE",
90
+ "SPECIFIC_LENGTH",
91
+ "SPECIFIC_SURFACE",
92
+ "SPECIFIC_VOLUME",
93
+ "STRESS",
94
+ "SURFACE_MASS_DENSITY",
95
+ "SURFACE_TENSION",
96
+ "TEMPERATURE",
97
+ "THERMAL_CONDUCTIVITY",
98
+ "TIME",
99
+ "TORQUE",
100
+ "TURBULENCE_ENERGY_DISSIPATION_RATE",
101
+ "VELOCITY_ANGULAR",
102
+ "VELOCITY_LINEAR",
103
+ "VISCOSITY_DYNAMIC",
104
+ "VISCOSITY_KINEMATIC",
105
+ "VOLUME",
106
+ "VOLUMETRIC_CALORIFIC_HEATING_VALUE",
107
+ "VOLUMETRIC_COEFFICIENT_OF_EXPANSION",
108
+ "VOLUMETRIC_FLOW_RATE",
109
+ "VOLUMETRIC_FLUX",
110
+ "VOLUMETRIC_MASS_FLOW_RATE",
111
+ "VOLUME_FRACTION_OF_I",
112
+ "WAVENUMBER"
113
+ ],
114
+ "unit_classes": [
115
+ "AbsorbedDoseUnits",
116
+ "AccelerationUnits",
117
+ "ActivationEnergyUnits",
118
+ "AmountOfSubstanceUnits",
119
+ "AnglePlaneUnits",
120
+ "AngleSolidUnits",
121
+ "AngularAccelerationUnits",
122
+ "AngularMomentumUnits",
123
+ "AreaPerUnitVolumeUnits",
124
+ "AreaUnits",
125
+ "AtomicWeightUnits",
126
+ "ConcentrationUnits",
127
+ "DimensionlessUnits",
128
+ "DynamicFluidityUnits",
129
+ "ElectricCapacitanceUnits",
130
+ "ElectricChargeUnits",
131
+ "ElectricCurrentIntensityUnits",
132
+ "ElectricDipoleMomentUnits",
133
+ "ElectricFieldStrengthUnits",
134
+ "ElectricInductanceUnits",
135
+ "ElectricPotentialUnits",
136
+ "ElectricResistanceUnits",
137
+ "ElectricalConductanceUnits",
138
+ "ElectricalPermittivityUnits",
139
+ "ElectricalResistivityUnits",
140
+ "EnergyFluxUnits",
141
+ "EnergyHeatWorkUnits",
142
+ "EnergyPerUnitAreaUnits",
143
+ "ForceBodyUnits",
144
+ "ForcePerUnitMassUnits",
145
+ "ForceUnits",
146
+ "FrequencyVoltageRatioUnits",
147
+ "FuelConsumptionUnits",
148
+ "HeatOfCombustionUnits",
149
+ "HeatOfFusionUnits",
150
+ "HeatOfVaporizationUnits",
151
+ "HeatTransferCoefficientUnits",
152
+ "IlluminanceUnits",
153
+ "KineticEnergyOfTurbulenceUnits",
154
+ "LengthUnits",
155
+ "LinearMassDensityUnits",
156
+ "LinearMomentumUnits",
157
+ "LuminanceSelfUnits",
158
+ "LuminousFluxUnits",
159
+ "LuminousIntensityUnits",
160
+ "MagneticFieldUnits",
161
+ "MagneticFluxUnits",
162
+ "MagneticInductionFieldStrengthUnits",
163
+ "MagneticMomentUnits",
164
+ "MagneticPermeabilityUnits",
165
+ "MagnetomotiveForceUnits",
166
+ "MassDensityUnits",
167
+ "MassFlowRateUnits",
168
+ "MassFluxUnits",
169
+ "MassFractionOfIUnits",
170
+ "MassTransferCoefficientUnits",
171
+ "MassUnits",
172
+ "MolalityOfSoluteIUnits",
173
+ "MolarConcentrationByMassUnits",
174
+ "MolarFlowRateUnits",
175
+ "MolarFluxUnits",
176
+ "MolarHeatCapacityUnits",
177
+ "MolarityOfIUnits",
178
+ "MoleFractionOfIUnits",
179
+ "MomentOfInertiaUnits",
180
+ "MomentumFlowRateUnits",
181
+ "MomentumFluxUnits",
182
+ "NormalityOfSolutionUnits",
183
+ "ParticleDensityUnits",
184
+ "PercentUnits",
185
+ "PermeabilityUnits",
186
+ "PhotonEmissionRateUnits",
187
+ "PowerPerUnitMassUnits",
188
+ "PowerPerUnitVolumeUnits",
189
+ "PowerThermalDutyUnits",
190
+ "PressureUnits",
191
+ "RadiationDoseEquivalentUnits",
192
+ "RadiationExposureUnits",
193
+ "RadioactivityUnits",
194
+ "SecondMomentOfAreaUnits",
195
+ "SecondRadiationConstantPlanckUnits",
196
+ "SpecificEnthalpyUnits",
197
+ "SpecificGravityUnits",
198
+ "SpecificHeatCapacityConstantPressureUnits",
199
+ "SpecificLengthUnits",
200
+ "SpecificSurfaceUnits",
201
+ "SpecificVolumeUnits",
202
+ "StressUnits",
203
+ "SurfaceMassDensityUnits",
204
+ "SurfaceTensionUnits",
205
+ "TemperatureUnits",
206
+ "ThermalConductivityUnits",
207
+ "TimeUnits",
208
+ "TorqueUnits",
209
+ "TurbulenceEnergyDissipationRateUnits",
210
+ "VelocityAngularUnits",
211
+ "VelocityLinearUnits",
212
+ "ViscosityDynamicUnits",
213
+ "ViscosityKinematicUnits",
214
+ "VolumeFractionOfIUnits",
215
+ "VolumeUnits",
216
+ "VolumetricCalorificHeatingValueUnits",
217
+ "VolumetricCoefficientOfExpansionUnits",
218
+ "VolumetricFlowRateUnits",
219
+ "VolumetricFluxUnits",
220
+ "VolumetricMassFlowRateUnits",
221
+ "WavenumberUnits"
222
+ ]
223
+ }
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script to generate comprehensive quantities.py for all variable types.
4
+
5
+ This script generates static quantity class definitions without setter classes.
6
+ The setter classes are generated separately in setters_gen.py.
7
+ """
8
+
9
+ from pathlib import Path
10
+
11
+ try:
12
+ from .data_processor import (
13
+ augment_with_prefixed_units,
14
+ calculate_statistics,
15
+ convert_to_class_name,
16
+ get_dimension_constant_name,
17
+ load_unit_data,
18
+ save_text_file,
19
+ setup_import_path,
20
+ )
21
+ from .doc_generator import generate_class_docstring, generate_init_method, generate_set_method
22
+ except ImportError:
23
+ # Handle standalone execution
24
+ import sys
25
+ from pathlib import Path
26
+ sys.path.insert(0, str(Path(__file__).parent))
27
+ from .data_processor import (
28
+ augment_with_prefixed_units,
29
+ calculate_statistics,
30
+ convert_to_class_name,
31
+ get_dimension_constant_name,
32
+ load_unit_data,
33
+ save_text_file,
34
+ setup_import_path,
35
+ )
36
+ from .doc_generator import generate_class_docstring, generate_init_method, generate_set_method
37
+
38
+
39
+ def generate_quantities(parsed_data: dict, dimension_mapping: dict) -> str:
40
+ """Generate the quantities.py content with static class definitions for performance."""
41
+ del dimension_mapping # Unused but kept for API compatibility
42
+
43
+ sorted_fields = sorted(parsed_data.items())
44
+ fields_with_units = [(k, v) for k, v in sorted_fields if v.get('units')]
45
+
46
+ lines = [
47
+ '"""',
48
+ 'Quantity Classes Module - Static Edition',
49
+ '========================================',
50
+ '',
51
+ 'Static quantity class definitions for maximum import performance.',
52
+ 'Uses static class generation instead of dynamic type() calls.',
53
+ 'Auto-generated from unit_data.json.',
54
+ '"""',
55
+ '',
56
+ 'from ..quantities.typed_quantity import TypedQuantity',
57
+ 'from . import dimensions as dim',
58
+ 'from . import setters as ts',
59
+ ''
60
+ ]
61
+
62
+ # Generate all quantity classes
63
+ lines.append('# ===== QUANTITY CLASSES =====')
64
+ lines.append('# Static quantity class definitions with __slots__ optimization')
65
+ lines.append('')
66
+
67
+ for field_name, field_data in fields_with_units:
68
+ class_name = convert_to_class_name(field_name)
69
+ setter_class_name = f"{class_name}Setter"
70
+ dimension_constant = get_dimension_constant_name(field_name)
71
+ display_name = field_data.get('field', class_name).lower()
72
+ units = field_data.get('units', [])
73
+ is_dimensionless = class_name == 'Dimensionless'
74
+
75
+ # Generate class declaration and docstring
76
+ lines.append(f'class {class_name}(TypedQuantity):')
77
+ lines.extend(generate_class_docstring(class_name, display_name, units, is_dimensionless))
78
+ # Class attributes
79
+ lines.append(' __slots__ = ()')
80
+ lines.append(f' _setter_class = ts.{setter_class_name}')
81
+ lines.append(f' _expected_dimension = dim.{dimension_constant}')
82
+ lines.append(' ')
83
+
84
+ # Generate __init__ method
85
+ lines.extend(generate_init_method(class_name, display_name, is_dimensionless, stub_only=False))
86
+
87
+ # Generate set method
88
+ lines.append(' ')
89
+ lines.extend(generate_set_method(setter_class_name, display_name, stub_only=False))
90
+ lines.append(' ')
91
+ lines.append('')
92
+
93
+ return '\n'.join(lines) + '\n'
94
+
95
+
96
+ def main():
97
+ """Main execution function."""
98
+ # Setup paths using pathlib
99
+ base_path = Path(__file__).parents[4] # Go up to qnty root
100
+ data_path = Path(__file__).parent / "data"
101
+ output_path = Path(__file__).parent / "out"
102
+ generated_path = base_path / "src" / "qnty" / "generated"
103
+
104
+ # Ensure output directories exist
105
+ output_path.mkdir(exist_ok=True)
106
+ generated_path.mkdir(exist_ok=True)
107
+
108
+ parsed_file = data_path / "unit_data.json"
109
+ dimension_file = output_path / "dimension_mapping.json"
110
+ output_file = generated_path / "quantities.py"
111
+
112
+ print("Loading parsed units data for quantities...")
113
+
114
+ # Setup import path and load data using shared processor
115
+ setup_import_path()
116
+ parsed_data = load_unit_data(parsed_file)
117
+ dimension_mapping = load_unit_data(dimension_file) if dimension_file.exists() else {}
118
+
119
+ print(f"Loaded {len(parsed_data)} fields with units")
120
+
121
+ # Augment data with missing prefixed units using shared processor
122
+ print("\nAugmenting data with missing prefixed units...")
123
+ augmented_data, generated_count = augment_with_prefixed_units(parsed_data)
124
+ print(f"Generated {generated_count} missing prefixed units for quantities")
125
+
126
+ # Count fields with units
127
+ fields_with_units = sum(1 for field_data in augmented_data.values() if field_data.get('units'))
128
+ print(f"Found {len(augmented_data)} total fields, {fields_with_units} fields with units")
129
+
130
+ # Generate quantities file
131
+ print("Generating quantities.py...")
132
+ content = generate_quantities(augmented_data, dimension_mapping)
133
+
134
+ # Write output file
135
+ save_text_file(content, output_file)
136
+ print(f"Generated quantities file: {output_file}")
137
+
138
+ # Print statistics using shared calculator
139
+ stats = calculate_statistics(augmented_data)
140
+ print("\nStatistics:")
141
+ print(f" Total fields: {stats['total_fields']}")
142
+ print(f" Fields with units: {fields_with_units}")
143
+ print(f" Original units: {stats['original_units']}")
144
+ print(f" Total units (with prefixes): {stats['total_units']}")
145
+ print(f" Generated prefixed units: {stats['generated_prefixed_units']}")
146
+
147
+ # Show top quantity types by unit count
148
+ fields_by_units = [(field_name, len(field_data.get('units', [])), field_data.get('field', ''))
149
+ for field_name, field_data in augmented_data.items() if field_data.get('units')]
150
+ fields_by_units.sort(key=lambda x: x[1], reverse=True)
151
+
152
+ print("\nTop quantity types by unit count:")
153
+ for field_name, unit_count, display_name in fields_by_units[:10]:
154
+ class_name = convert_to_class_name(field_name)
155
+ print(f" {class_name:<25} : {unit_count:>3} units ({display_name})")
156
+
157
+
158
+ if __name__ == "__main__":
159
+ main()
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Script to generate comprehensive setters.py for all variable setters.
4
+
5
+ This script generates static setter class definitions with unit properties
6
+ for the fluent API with dimension-specific unit properties.
7
+ """
8
+
9
+ from pathlib import Path
10
+
11
+ try:
12
+ from .data_processor import (
13
+ augment_with_prefixed_units,
14
+ calculate_statistics,
15
+ convert_to_class_name,
16
+ get_dimension_constant_name,
17
+ get_unit_names_and_aliases,
18
+ load_unit_data,
19
+ save_text_file,
20
+ setup_import_path,
21
+ )
22
+ except ImportError:
23
+ from .data_processor import (
24
+ augment_with_prefixed_units,
25
+ calculate_statistics,
26
+ convert_to_class_name,
27
+ get_dimension_constant_name,
28
+ get_unit_names_and_aliases,
29
+ load_unit_data,
30
+ save_text_file,
31
+ setup_import_path,
32
+ )
33
+
34
+
35
+ def generate_setters(parsed_data: dict, dimension_mapping: dict) -> str:
36
+ """Generate the setters.py content with static setter class definitions."""
37
+
38
+ sorted_fields = sorted(parsed_data.items())
39
+ fields_with_units = [(k, v) for k, v in sorted_fields if v.get('units')]
40
+
41
+ lines = [
42
+ '"""',
43
+ 'Setter Classes Module - Static Edition',
44
+ '======================================',
45
+ '',
46
+ 'Static setter class definitions for maximum import performance.',
47
+ 'Provides fluent API unit properties for all variable types.',
48
+ 'Auto-generated from unit_data.json.',
49
+ '"""',
50
+ '',
51
+ 'from ..quantities.quantity import Quantity, TypeSafeSetter',
52
+ 'from . import units',
53
+ ''
54
+ ]
55
+
56
+ # Generate all setter classes
57
+ lines.append('# ===== SETTER CLASSES =====')
58
+ lines.append('# Static setter class definitions with __slots__ optimization')
59
+ lines.append('')
60
+
61
+ for field_name, field_data in fields_with_units:
62
+ class_name = convert_to_class_name(field_name)
63
+ setter_class_name = f"{class_name}Setter"
64
+ get_dimension_constant_name(field_name)
65
+ units_class_name = f"{class_name}Units"
66
+
67
+ lines.append(f'class {setter_class_name}(TypeSafeSetter):')
68
+ lines.append(f' """{class_name}-specific setter with optimized unit properties."""')
69
+ lines.append(' __slots__ = ()')
70
+ lines.append(' ')
71
+
72
+ # Generate property for each unit, avoiding duplicates
73
+ generated_properties = set()
74
+
75
+ for unit_data in field_data['units']:
76
+ primary_name, aliases = get_unit_names_and_aliases(unit_data)
77
+ # Use primary name for the main property
78
+ property_name = primary_name
79
+
80
+ # Skip if this property name was already generated
81
+ if property_name in generated_properties:
82
+ continue
83
+
84
+ generated_properties.add(property_name)
85
+
86
+ lines.append(' @property')
87
+ lines.append(f' def {property_name}(self):')
88
+ unit_display_name = unit_data.get('name', primary_name)
89
+ # Escape backslashes in the docstring to avoid escape sequence warnings
90
+ escaped_name = unit_display_name.replace('\\', '\\\\')
91
+ lines.append(f' """Set value using {escaped_name} units."""')
92
+ lines.append(f' unit_const = units.{units_class_name}.{property_name}')
93
+ lines.append(' self.variable.quantity = Quantity(self.value, unit_const)')
94
+ lines.append(' return self.variable')
95
+ lines.append(' ')
96
+
97
+ # Add alias properties using shared processing
98
+ for alias in aliases:
99
+ # Only add if different from main property and not already generated
100
+ if (alias != property_name and
101
+ alias.isidentifier() and
102
+ alias not in generated_properties):
103
+ generated_properties.add(alias)
104
+ lines.append(' @property')
105
+ lines.append(f' def {alias}(self):')
106
+ lines.append(f' """Set value using {alias} units (alias for {primary_name})."""')
107
+ lines.append(f' return self.{property_name}')
108
+ lines.append(' ')
109
+
110
+ lines.append('')
111
+
112
+ return '\n'.join(lines) + '\n'
113
+
114
+
115
+ def main():
116
+ """Main execution function."""
117
+ # Setup paths using pathlib
118
+ base_path = Path(__file__).parents[4] # Go up to qnty root
119
+ data_path = Path(__file__).parent / "data"
120
+ output_path = Path(__file__).parent / "out"
121
+ generated_path = base_path / "src" / "qnty" / "generated"
122
+
123
+ # Ensure output directories exist
124
+ output_path.mkdir(exist_ok=True)
125
+ generated_path.mkdir(exist_ok=True)
126
+
127
+ parsed_file = data_path / "unit_data.json"
128
+ dimension_file = output_path / "dimension_mapping.json"
129
+ output_file = generated_path / "setters.py"
130
+
131
+ print("Loading parsed units data for setters...")
132
+
133
+ # Setup import path and load data using shared processor
134
+ setup_import_path()
135
+ parsed_data = load_unit_data(parsed_file)
136
+ dimension_mapping = load_unit_data(dimension_file) if dimension_file.exists() else {}
137
+
138
+ print(f"Loaded {len(parsed_data)} fields with units")
139
+
140
+ # Augment data with missing prefixed units using shared processor
141
+ print("\nAugmenting data with missing prefixed units...")
142
+ augmented_data, generated_count = augment_with_prefixed_units(parsed_data)
143
+ print(f"Generated {generated_count} missing prefixed units for setters")
144
+
145
+ # Count fields with units
146
+ fields_with_units = sum(1 for field_data in augmented_data.values() if field_data.get('units'))
147
+ print(f"Found {len(augmented_data)} total fields, {fields_with_units} fields with units")
148
+
149
+ # Generate setters file
150
+ print("Generating setters.py...")
151
+ content = generate_setters(augmented_data, dimension_mapping)
152
+
153
+ # Write output file
154
+ save_text_file(content, output_file)
155
+ print(f"Generated setters file: {output_file}")
156
+
157
+ # Print statistics using shared calculator
158
+ stats = calculate_statistics(augmented_data)
159
+ print("\nStatistics:")
160
+ print(f" Total fields: {stats['total_fields']}")
161
+ print(f" Fields with units: {fields_with_units}")
162
+ print(f" Original units: {stats['original_units']}")
163
+ print(f" Total units (with prefixes): {stats['total_units']}")
164
+ print(f" Generated prefixed units: {stats['generated_prefixed_units']}")
165
+
166
+ # Show top setter types by unit count
167
+ fields_by_units = [(field_name, len(field_data.get('units', [])), field_data.get('field', ''))
168
+ for field_name, field_data in augmented_data.items() if field_data.get('units')]
169
+ fields_by_units.sort(key=lambda x: x[1], reverse=True)
170
+
171
+ print("\nTop setter types by unit property count:")
172
+ for field_name, unit_count, display_name in fields_by_units[:10]:
173
+ class_name = convert_to_class_name(field_name)
174
+ print(f" {class_name}Setter{'':<15} : {unit_count:>3} properties ({display_name})")
175
+
176
+
177
+ if __name__ == "__main__":
178
+ main()