mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-26 07:00:17 -05:00
#14001 Python: Drop hand-written PropertyType, use auto-generated PropertyType
Consolidate the hand-written PropertyType / NNCPropertyType enums in enums.py into the auto-generated StrEnum classes that already exist in generated_classes.py. enums.py and all its imports are removed. The auto-generated class for caf::AppEnum<RiaDefines::ResultCatType> was named "ResultType" because the existing scriptable m_resultType fields used keyword "ResultType". Switch those fields to CAF_PDM_InitScriptableFieldWithScriptKeywordNoDefault, keeping the XML keyword "ResultType" (so project files still load) but exposing the script keyword as "PropertyType". The generator now emits a single PropertyType StrEnum that: - matches the proto PropertyType for setters (FLOAT/INTEGER aside, the members callers actually use are identical), - gains ALLAN_DIAGRAMS that the C++ side already knew about, - loses the proto-only REMOVED/UNDEFINED sentinels (unused in any Python caller). rips.NNCPropertyType was exported but unreferenced anywhere — dropped. Updated Python callers: - rips.ResultType.X -> rips.PropertyType.X across examples and tests. - result_type= kwarg / .result_type attribute -> property_type / .property_type (the script keyword change renamed those everywhere the affected PdmObject fields are accessed from Python). - view.apply_cell_result's hand-written wrapper now takes property_type instead of result_type and forwards via cell_result.property_type. All 271 Python tests pass, ruff and clang-format clean.
This commit is contained in:
1 parent
a6c3ac2d1a
commit
01ceb57323
19 files changed
+126
-71
No files matched your search
@@ -23,6 +23,7 @@
|
||||
#include "RiaResultNames.h"
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
#include "cafPdmScriptEnumNameRegistry.h"
|
||||
|
||||
namespace caf
|
||||
{
|
||||
@@ -179,6 +180,19 @@ void caf::AppEnum<RiaDefines::RowCount>::setUp()
|
||||
|
||||
} // namespace caf
|
||||
|
||||
namespace
|
||||
{
|
||||
// Pin the Python StrEnum class name for caf::AppEnum<RiaDefines::ResultCatType> to "PropertyType".
|
||||
// Without this override the generator derives the class name from the first field's script keyword
|
||||
// ("ResultType"), which both diverges from the proto PropertyType name and shifts whenever class
|
||||
// iteration order changes.
|
||||
struct RegisterScriptEnumNames
|
||||
{
|
||||
RegisterScriptEnumNames() { caf::PdmScriptEnumNameRegistry::registerName<RiaDefines::ResultCatType>( "PropertyType" ); }
|
||||
};
|
||||
const RegisterScriptEnumNames s_registerScriptEnumNames;
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -16,6 +16,7 @@ set(PROJECT_FILES
|
||||
cafPdmDataContainerEnum.cpp
|
||||
cafPdmObjectMethod.h
|
||||
cafPdmObjectMethod.cpp
|
||||
cafPdmScriptEnumNameRegistry.h
|
||||
cafPdmObjectScriptingCapabilityRegister.h
|
||||
cafPdmObjectScriptingCapabilityRegister.cpp
|
||||
cafPdmPythonGenerator.h
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "cafPdmObjectMethod.h"
|
||||
#include "cafPdmObjectScriptingCapabilityRegister.h"
|
||||
#include "cafPdmProxyValueField.h"
|
||||
#include "cafPdmScriptEnumNameRegistry.h"
|
||||
#include "cafPdmXmlFieldHandle.h"
|
||||
|
||||
#ifndef CAF_EXCLUDE_CVF
|
||||
@@ -216,7 +217,10 @@ QString caf::PdmPythonGenerator::generate( PdmObjectFactory* factory, std::vecto
|
||||
auto cached = enumClassNameByDataTypeName.find( dataTypeName );
|
||||
if ( cached != enumClassNameByDataTypeName.end() ) return cached->second;
|
||||
|
||||
QString baseName = snakeToCamelCase( camelToSnakeCase( scriptability->scriptFieldName() ) );
|
||||
// Prefer an explicit override registered by application code so the Python enum class name
|
||||
// is stable independent of which field the generator visits first.
|
||||
QString baseName = PdmScriptEnumNameRegistry::lookup( dataTypeName );
|
||||
if ( baseName.isEmpty() ) baseName = snakeToCamelCase( camelToSnakeCase( scriptability->scriptFieldName() ) );
|
||||
if ( baseName.isEmpty() ) baseName = "Enum";
|
||||
|
||||
QString candidate = baseName;
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
//##################################################################################################
|
||||
//
|
||||
// Custom Visualization Core library
|
||||
// Copyright (C) 2026- Equinor ASA
|
||||
//
|
||||
// This library may be used under the terms of either the GNU General Public License or
|
||||
// the GNU Lesser General Public License as follows:
|
||||
//
|
||||
// GNU General Public License Usage
|
||||
// This library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
|
||||
// for more details.
|
||||
//
|
||||
// GNU Lesser General Public License Usage
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
|
||||
// for more details.
|
||||
//
|
||||
//##################################################################################################
|
||||
#pragma once
|
||||
|
||||
#include "cafAppEnum.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <map>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace caf
|
||||
{
|
||||
//==================================================================================================
|
||||
/// Optional override for the Python StrEnum class name the code generator emits for a given
|
||||
/// caf::AppEnum<T>. Without an override, the generator derives the class name from the script
|
||||
/// keyword of the first field it visits — which is sensitive to class/iteration order. Use this
|
||||
/// registry to pin a canonical Python name for an AppEnum, independent of any field's script
|
||||
/// keyword.
|
||||
//==================================================================================================
|
||||
class PdmScriptEnumNameRegistry
|
||||
{
|
||||
public:
|
||||
template <typename EnumType>
|
||||
static void registerName( const QString& scriptClassName )
|
||||
{
|
||||
registry()[QString::fromLatin1( typeid( caf::AppEnum<EnumType> ).name() )] = scriptClassName;
|
||||
}
|
||||
|
||||
static QString lookup( const QString& dataTypeName )
|
||||
{
|
||||
const auto& m = registry();
|
||||
auto it = m.find( dataTypeName );
|
||||
if ( it == m.end() ) return QString();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
static std::map<QString, QString>& registry()
|
||||
{
|
||||
static std::map<QString, QString> s_map;
|
||||
return s_map;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace caf
|
||||
+1
-1
@@ -21,4 +21,4 @@ case_group = resinsight.project.create_grid_case_group(case_paths=case_paths)
|
||||
case_group.compute_statistics()
|
||||
|
||||
view = case_group.views()[0]
|
||||
view.apply_cell_result(rips.ResultType.DYNAMIC_NATIVE, "PRESSURE_DEV")
|
||||
view.apply_cell_result(rips.PropertyType.DYNAMIC_NATIVE, "PRESSURE_DEV")
|
||||
+1
-1
@@ -45,4 +45,4 @@ case.set_active_cell_property_async(
|
||||
end = time.time()
|
||||
print("Time elapsed: ", end - start)
|
||||
print("Transferred all results back")
|
||||
view = case.views()[0].apply_cell_result(rips.ResultType.GENERATED, "POROPERMXAS")
|
||||
view = case.views()[0].apply_cell_result(rips.PropertyType.GENERATED, "POROPERMXAS")
|
||||
+1
-1
@@ -97,6 +97,6 @@ print(f" Unassigned (no polygon): {unassigned} cells")
|
||||
# Apply the generated result in the view to visualize the regions
|
||||
view = case.views()[0] if case.views() else case.create_view()
|
||||
view.apply_cell_result(
|
||||
result_type=rips.ResultType.GENERATED, result_variable=property_name
|
||||
result_type=rips.PropertyType.GENERATED, result_variable=property_name
|
||||
)
|
||||
print(f"Applied '{property_name}' cell result to view")
|
||||
+3
-1
@@ -6,4 +6,6 @@ import rips
|
||||
resinsight = rips.Instance.find()
|
||||
|
||||
view = resinsight.project.views()[0]
|
||||
view.apply_cell_result(result_type=rips.ResultType.STATIC_NATIVE, result_variable="DX")
|
||||
view.apply_cell_result(
|
||||
result_type=rips.PropertyType.STATIC_NATIVE, result_variable="DX"
|
||||
)
|
||||
+1
-1
@@ -51,4 +51,4 @@ print("Time elapsed: ", end - start)
|
||||
|
||||
print("Transferred all results back")
|
||||
|
||||
view = case.views()[0].apply_cell_result(rips.ResultType.GENERATED, "SOILPORVAsync")
|
||||
view = case.views()[0].apply_cell_result(rips.PropertyType.GENERATED, "SOILPORVAsync")
|
||||
@@ -34,4 +34,4 @@ print("Time elapsed: ", end - start)
|
||||
|
||||
print("Transferred all results back")
|
||||
|
||||
view = case.views()[0].apply_cell_result(rips.ResultType.GENERATED, "SOILPORVSync")
|
||||
view = case.views()[0].apply_cell_result(rips.PropertyType.GENERATED, "SOILPORVSync")
|
||||
@@ -38,7 +38,7 @@ for case in cases:
|
||||
for view in case.views():
|
||||
for property in property_list:
|
||||
view.apply_cell_result(
|
||||
result_type=rips.ResultType.DYNAMIC_NATIVE, result_variable=property
|
||||
result_type=rips.PropertyType.DYNAMIC_NATIVE, result_variable=property
|
||||
)
|
||||
for time_step in range(0, len(time_steps), 10):
|
||||
view.set_time_step(time_step=time_step)
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ view1.set_time_step(time_step=2)
|
||||
|
||||
# Set cell result to SOIL
|
||||
view1.apply_cell_result(
|
||||
result_type=rips.ResultType.DYNAMIC_NATIVE, result_variable="SOIL"
|
||||
result_type=rips.PropertyType.DYNAMIC_NATIVE, result_variable="SOIL"
|
||||
)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ view1.set_time_step(time_step=2)
|
||||
|
||||
# Set cell result to SOIL
|
||||
view1.apply_cell_result(
|
||||
result_type=rips.ResultType.DYNAMIC_NATIVE, result_variable="SOIL"
|
||||
result_type=rips.PropertyType.DYNAMIC_NATIVE, result_variable="SOIL"
|
||||
)
|
||||
|
||||
# Set export folder for snapshots and properties
|
||||
|
||||
+2
-2
@@ -45,14 +45,14 @@ print("Overburden: ", stim_plan_model_template.overburden_formation)
|
||||
|
||||
# Set eclipse result for facies definition
|
||||
eclipse_result = stim_plan_model_template.facies_properties().facies_definition()
|
||||
eclipse_result.result_type = rips.ResultType.INPUT_PROPERTY
|
||||
eclipse_result.result_type = rips.PropertyType.INPUT_PROPERTY
|
||||
eclipse_result.result_variable = "OPERNUM_1"
|
||||
eclipse_result.update()
|
||||
|
||||
# Set eclipse result for non-net layers
|
||||
non_net_layers = stim_plan_model_template.non_net_layers()
|
||||
non_net_layers_result = non_net_layers.facies_definition()
|
||||
non_net_layers_result.result_type = rips.ResultType.STATIC_NATIVE
|
||||
non_net_layers_result.result_type = rips.PropertyType.STATIC_NATIVE
|
||||
non_net_layers_result.result_variable = "NTG"
|
||||
non_net_layers_result.update()
|
||||
non_net_layers.formation = "Not"
|
||||
|
||||
+4
-4
@@ -12,10 +12,10 @@ home_dir = expanduser("~")
|
||||
|
||||
|
||||
properties = [
|
||||
(rips.ResultType.STATIC_NATIVE, "INDEX_K", 0),
|
||||
(rips.ResultType.STATIC_NATIVE, "PORO", 0),
|
||||
(rips.ResultType.STATIC_NATIVE, "PERMX", 0),
|
||||
(rips.ResultType.DYNAMIC_NATIVE, "PRESSURE", 0),
|
||||
(rips.PropertyType.STATIC_NATIVE, "INDEX_K", 0),
|
||||
(rips.PropertyType.STATIC_NATIVE, "PORO", 0),
|
||||
(rips.PropertyType.STATIC_NATIVE, "PERMX", 0),
|
||||
(rips.PropertyType.DYNAMIC_NATIVE, "PRESSURE", 0),
|
||||
]
|
||||
|
||||
export_folder = tempfile.mkdtemp()
|
||||
|
||||
@@ -30,15 +30,6 @@ from .surface import RegularSurface as RegularSurface # noqa: E402
|
||||
from . import well_events as well_events # noqa: F401, E402
|
||||
from . import category_mapping as category_mapping # noqa: F401, E402
|
||||
|
||||
# Enums for proto types not visible to the AppEnum auto-generator.
|
||||
# PorosityModelType and PropertyDataType are auto-generated into resinsight_classes
|
||||
# (already imported above) and intentionally not re-imported here to avoid a
|
||||
# duplicate symbol.
|
||||
from .enums import ( # noqa: E402
|
||||
PropertyType as PropertyType,
|
||||
NNCPropertyType as NNCPropertyType,
|
||||
)
|
||||
|
||||
__all__: List[str] = []
|
||||
for key in class_dict(): # noqa: F405
|
||||
__all__.append(key)
|
||||
@@ -47,10 +38,13 @@ for key in class_dict(): # noqa: F405
|
||||
__all__.append("Grid")
|
||||
__all__.append("Instance")
|
||||
|
||||
# PropertyType, PropertyDataType, and PorosityModelType are auto-generated
|
||||
# StrEnum classes (driven by their caf::AppEnum<T> registrations) that the
|
||||
# wildcard import above pulls in but class_dict() does not list.
|
||||
for _enum_name in (
|
||||
"PropertyType",
|
||||
"PorosityModelType",
|
||||
"PropertyDataType",
|
||||
"NNCPropertyType",
|
||||
"PropertyType",
|
||||
):
|
||||
if _enum_name not in __all__:
|
||||
__all__.append(_enum_name)
|
||||
|
||||
@@ -55,6 +55,7 @@ from .resinsight_classes import (
|
||||
GeoMechCase as GeoMechCase,
|
||||
PorosityModelType as PorosityModelType,
|
||||
PropertyDataType as PropertyDataType,
|
||||
PropertyType as PropertyType,
|
||||
Reservoir as Reservoir,
|
||||
WellBoreStabilityPlot as WellBoreStabilityPlot,
|
||||
WbsParameters as WbsParameters,
|
||||
@@ -66,9 +67,6 @@ from .project import Project as Project
|
||||
from .pdmobject import add_method
|
||||
from .view import View as View
|
||||
from .simulation_well import SimulationWell
|
||||
from .enums import (
|
||||
PropertyType,
|
||||
)
|
||||
import rips.project # full name import due to circular dependency
|
||||
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
"""Typed enums mirroring the proto enums used by the rips.case API.
|
||||
|
||||
These are hand-written counterparts to proto enums defined in ``Properties.proto``
|
||||
and ``NNCProperties.proto``. They give users typed, autocompletable enum members
|
||||
while remaining wire-compatible with the existing string-based API (``StrEnum``
|
||||
members are strings).
|
||||
|
||||
Auto-generated ``StrEnum`` classes for ``caf::AppEnum`` scriptable fields and for
|
||||
PdmObjectMethod enum return values live in ``rips.generated.generated_classes``
|
||||
and are emitted by ``cafPdmPythonGenerator``. ``PorosityModelType`` and
|
||||
``PropertyDataType`` are auto-generated and imported from ``resinsight_classes``;
|
||||
the enums in this module cover the gRPC-only proto enums that the auto-generator
|
||||
does not see.
|
||||
"""
|
||||
|
||||
from enum import StrEnum
|
||||
|
||||
|
||||
# Keep in sync with PropertyType in GrpcInterface/GrpcProtos/Properties.proto
|
||||
class PropertyType(StrEnum):
|
||||
DYNAMIC_NATIVE = "DYNAMIC_NATIVE"
|
||||
STATIC_NATIVE = "STATIC_NATIVE"
|
||||
SOURSIMRL = "SOURSIMRL"
|
||||
GENERATED = "GENERATED"
|
||||
INPUT_PROPERTY = "INPUT_PROPERTY"
|
||||
FORMATION_NAMES = "FORMATION_NAMES"
|
||||
FLOW_DIAGNOSTICS = "FLOW_DIAGNOSTICS"
|
||||
INJECTION_FLOODING = "INJECTION_FLOODING"
|
||||
REMOVED = "REMOVED"
|
||||
UNDEFINED = "UNDEFINED"
|
||||
|
||||
|
||||
# Keep in sync with NNCPropertyType in GrpcInterface/GrpcProtos/NNCProperties.proto
|
||||
class NNCPropertyType(StrEnum):
|
||||
NNC_DYNAMIC = "NNC_DYNAMIC"
|
||||
NNC_STATIC = "NNC_STATIC"
|
||||
NNC_GENERATED = "NNC_GENERATED"
|
||||
@@ -26,10 +26,10 @@ def test_10k_well_log_extraction(rips_instance, initialize_test):
|
||||
well_path = wells[0]
|
||||
|
||||
properties = [
|
||||
(rips.ResultType.STATIC_NATIVE, "INDEX_K", 0),
|
||||
(rips.ResultType.STATIC_NATIVE, "PORO", 0),
|
||||
(rips.ResultType.STATIC_NATIVE, "PERMX", 0),
|
||||
(rips.ResultType.DYNAMIC_NATIVE, "PRESSURE", 0),
|
||||
(rips.PropertyType.STATIC_NATIVE, "INDEX_K", 0),
|
||||
(rips.PropertyType.STATIC_NATIVE, "PORO", 0),
|
||||
(rips.PropertyType.STATIC_NATIVE, "PERMX", 0),
|
||||
(rips.PropertyType.DYNAMIC_NATIVE, "PRESSURE", 0),
|
||||
]
|
||||
|
||||
well_log_plot_collection = rips_instance.project.descendants(
|
||||
|
||||
Reference in new issue
Block a user