Description
Overview
We need to convert the lambda functions and derived types to be saved as string objects in a generated AIR.json
file. The reason for this change is to support the portability of GrFN objects (a lambdas Python file is path-dependent during evaluation/execution). Completing this change will remove the necessity for outputting a _lambdas.py
file.
@skdebray and @cl4yton, I am adding you both to this GH issue so you can track the progress.
Task assignments
- @pratikbhd: convert the lambda function generation to the new stringification style (see examples below)
- @hlim1: convert the derived type generation to the new stringification style (see the example derived-type below)
- @pauldhein: Create a secure sandbox that allows us to use
eval()
andexec()
to load lambda functions and derived types without compromising security for future users of GrFN JSON
If anyone has any questions about their individual tasks please add a comment in this GH issue and mention me in the comment.
Lambda function examples
Examples
# Example 1 ==========================================
# Old style
def PETPT__petpt__IF_0__assign__albedo__1(msalb: Real, xhlai: Real):
return 0.23 - ((0.23 - msalb) * np.exp(-((0.75 * xhlai))))
# New style
"lambda msalb,xhlai:(0.23-((0.23-msalb)*np.exp(-((0.75*xhlai)))))"
# ====================================================
# Example 2 ==========================================
# Old style
def PETPNO__petpno__assign__sbzcon__0():
return 4.903e-09
# New style
"lambda :4.903e-09"
# ====================================================
# Example 3 ==========================================
# Old style
def PETPT__petpt__IF_0__decision__albedo__2(
COND_0, albedo_0: Real, albedo_1: Real
):
return albedo_0 if COND_0 else albedo_1
# New style
"lambda COND_0,albedo_0,albedo_1:albedo_0 if COND_0 else albedo_1"
# ====================================================
# Example 4 ==========================================
# Old style
def some_fake_lambda(x, y, z):
return x+y, y+z, x+z
# New style
"lambda x,y,z:(x+y,y+z,x+z)"
# ====================================================
Important notes
- Use minimal spacing when creating these strings as I have shown above
- Type identifiers are going to be dropped in this representation (extra
:
are illegal in lambda expressions) - Parentheses must be used if we ever end up returning more than a single object from a lambda expression
Derived-type example
In this section I am providing an example of a derived type from Fortran. @hlim1 I am going to show what the current derived-type class code should look like in the current form, and then I will show how to stringify that.
Original Fortran
type soiltype
integer nlayr
character (len=10) slno
character(len=12), dimension(nl) :: texture
character*50 sldesc, taxon
logical, dimension(nl) :: coarse
real ales, dmod
real, dimension(nl) :: alphavg
end type soiltype
Current python output
@dataclass
class soiltype:
nlayr: int
slno: str
texture: List[str]
sldesc: str
taxon: str
coarse: List[bool]
ales: float
dmod: float
alphavg: List[float]
Stringified form
"@dataclass\nclass soiltype:\n\tnlayr:int\n\tslno:str\n\ttexture:List[str]\n\tsldesc:str\n\ttaxon:str\n\tcoarse:List[bool]\n\tales:float\n\tdmod:float\n\talphavg:List[float]"
Important notes
- The
List
annotation is imported from the pythontypes
module and it needs to be capitalized - No spaces are necessary between the colon and the type annotation
- The following sequence is needed before each new data member:
\n\t
- A newline character is added after
@dataclass
and a space is necessary after theclass
keyword