Skip to content

Commit 636ad00

Browse files
authored
Merge pull request #340 from equinor/add-stubs
Add stubs
2 parents ad43485 + 5c38610 commit 636ad00

File tree

270 files changed

+29431
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

270 files changed

+29431
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Generate Java Stubs
2+
3+
on:
4+
# Run when JAR files are updated
5+
push:
6+
paths:
7+
- 'src/neqsim/lib/**/*.jar'
8+
# Run on release
9+
release:
10+
types: [published]
11+
# Allow manual trigger
12+
workflow_dispatch:
13+
14+
jobs:
15+
generate-stubs:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: '3.11'
25+
26+
- name: Set up Java
27+
uses: actions/setup-java@v4
28+
with:
29+
distribution: 'temurin'
30+
java-version: '17'
31+
32+
- name: Install dependencies
33+
run: |
34+
pip install poetry
35+
poetry install --with dev
36+
37+
- name: Generate stubs
38+
run: |
39+
poetry run python scripts/generate_stubs.py
40+
41+
- name: Commit updated stubs
42+
uses: stefanzweifel/git-auto-commit-action@v5
43+
with:
44+
commit_message: "chore: regenerate Java stubs"
45+
file_pattern: "src/jneqsim-stubs/**"

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ tabulate = { version = "^0.9.0", optional = true }
2727
black = ">=23.12,<25.0"
2828
pytest = "^7.4.3"
2929
pre-commit = "^3.5.0" # Higher versions require python 3.9+
30+
stubgenj = "^0.2.12" # Generate type stubs for Java classes
3031

3132
[tool.poetry.extras]
3233
interactive = ["matplotlib", "jupyter", "tabulate"]

scripts/generate_stubs.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
Script to generate Python type stubs for neqsim Java classes using stubgenj.
3+
4+
This enables IDE autocompletion and type checking for the neqsim Java library
5+
accessed via JPype.
6+
7+
The Java package 'neqsim' is exposed as 'jneqsim' in Python to avoid naming
8+
conflicts with the Python 'neqsim' package. The stubs are generated accordingly.
9+
10+
Usage:
11+
python scripts/generate_stubs.py
12+
13+
The stubs will be generated in the src/jneqsim-stubs directory.
14+
"""
15+
16+
import re
17+
import shutil
18+
import sys
19+
from pathlib import Path
20+
21+
# Add src to path
22+
src_path = Path(__file__).parent.parent / "src"
23+
sys.path.insert(0, str(src_path))
24+
25+
26+
def rename_package_in_stubs(stubs_dir: Path, old_name: str, new_name: str):
27+
"""
28+
Rename all references from old_name to new_name in stub files.
29+
This handles the neqsim -> jneqsim renaming to avoid conflicts
30+
with the Python neqsim package.
31+
"""
32+
for pyi_file in stubs_dir.rglob("*.pyi"):
33+
content = pyi_file.read_text(encoding="utf-8")
34+
35+
# Replace import statements and type references
36+
# Match 'neqsim.' but not 'jneqsim.' (negative lookbehind)
37+
new_content = re.sub(
38+
rf"(?<!j){old_name}\.", f"{new_name}.", content
39+
)
40+
41+
if new_content != content:
42+
pyi_file.write_text(new_content, encoding="utf-8")
43+
44+
45+
def generate_stubs():
46+
"""Generate type stubs for neqsim Java classes."""
47+
import jpype
48+
import jpype.imports # Enable Java imports
49+
import stubgenj
50+
51+
# Start JVM if not already started
52+
if not jpype.isJVMStarted():
53+
# Import neqsim to start JVM with correct classpath
54+
import neqsim # noqa: F401
55+
56+
# Import the neqsim Java package to get JPackage reference
57+
from neqsim.neqsimpython import jneqsim
58+
59+
# Temporary output directory (stubgenj will create 'neqsim-stubs')
60+
temp_output_dir = src_path / "temp-stubs"
61+
if temp_output_dir.exists():
62+
shutil.rmtree(temp_output_dir)
63+
temp_output_dir.mkdir(exist_ok=True)
64+
65+
# Final output directory
66+
final_output_dir = src_path / "jneqsim-stubs"
67+
68+
print("Generating stubs...")
69+
70+
# Generate stubs for the neqsim package (pass JPackage objects)
71+
stubgenj.generateJavaStubs(
72+
parentPackages=[jneqsim], # The neqsim JPackage
73+
useStubsSuffix=True, # Creates neqsim-stubs folder structure
74+
outputDir=str(temp_output_dir),
75+
jpypeJPackageStubs=True, # Include jpype stubs
76+
includeJavadoc=True, # Include javadoc in stubs
77+
)
78+
79+
# Rename neqsim -> jneqsim in all stub files to avoid conflict
80+
# with Python neqsim package
81+
neqsim_stubs = temp_output_dir / "neqsim-stubs"
82+
if neqsim_stubs.exists():
83+
print("Renaming 'neqsim' -> 'jneqsim' in stubs to avoid naming conflict...")
84+
rename_package_in_stubs(temp_output_dir, "neqsim", "jneqsim")
85+
86+
# Clean up existing output
87+
if final_output_dir.exists():
88+
shutil.rmtree(final_output_dir)
89+
final_output_dir.mkdir(exist_ok=True)
90+
91+
# Move jpype-stubs as-is (it's at temp_output_dir/jpype-stubs)
92+
jpype_stubs = temp_output_dir / "jpype-stubs"
93+
if jpype_stubs.exists():
94+
shutil.move(str(jpype_stubs), str(final_output_dir / "jpype-stubs"))
95+
96+
# Rename folder neqsim-stubs -> jneqsim-stubs
97+
target = final_output_dir / "jneqsim-stubs"
98+
shutil.move(str(neqsim_stubs), str(target))
99+
100+
# Clean up temp directory
101+
shutil.rmtree(temp_output_dir)
102+
103+
print(f"Stubs generated successfully in {final_output_dir}")
104+
print("\n" + "=" * 60)
105+
print("USAGE INSTRUCTIONS")
106+
print("=" * 60)
107+
print("\nThe Java 'neqsim' package stubs are available as 'jneqsim'")
108+
print("to avoid conflicts with the Python 'neqsim' package.")
109+
print("\nFor VS Code with Pylance, add to settings.json:")
110+
print(' "python.analysis.extraPaths": ["src/jneqsim-stubs"]')
111+
print("\nFor mypy, add to pyproject.toml:")
112+
print(' [tool.mypy]')
113+
print(' mypy_path = "src/jneqsim-stubs"')
114+
115+
116+
if __name__ == "__main__":
117+
generate_stubs()
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
import sys
3+
if sys.version_info >= (3, 8):
4+
from typing import Protocol
5+
else:
6+
from typing_extensions import Protocol
7+
8+
import jneqsim.api
9+
import jneqsim.blackoil
10+
import jneqsim.chemicalreactions
11+
import jneqsim.datapresentation
12+
import jneqsim.fluidmechanics
13+
import jneqsim.mathlib
14+
import jneqsim.physicalproperties
15+
import jneqsim.process
16+
import jneqsim.pvtsimulation
17+
import jneqsim.standards
18+
import jneqsim.statistics
19+
import jneqsim.thermo
20+
import jneqsim.thermodynamicoperations
21+
import jneqsim.util
22+
import typing
23+
24+
25+
class __module_protocol__(Protocol):
26+
# A module protocol which reflects the result of ``jp.JPackage("neqsim")``.
27+
28+
api: jneqsim.api.__module_protocol__
29+
blackoil: jneqsim.blackoil.__module_protocol__
30+
chemicalreactions: jneqsim.chemicalreactions.__module_protocol__
31+
datapresentation: jneqsim.datapresentation.__module_protocol__
32+
fluidmechanics: jneqsim.fluidmechanics.__module_protocol__
33+
mathlib: jneqsim.mathlib.__module_protocol__
34+
physicalproperties: jneqsim.physicalproperties.__module_protocol__
35+
process: jneqsim.process.__module_protocol__
36+
pvtsimulation: jneqsim.pvtsimulation.__module_protocol__
37+
standards: jneqsim.standards.__module_protocol__
38+
statistics: jneqsim.statistics.__module_protocol__
39+
thermo: jneqsim.thermo.__module_protocol__
40+
thermodynamicoperations: jneqsim.thermodynamicoperations.__module_protocol__
41+
util: jneqsim.util.__module_protocol__
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
import sys
3+
if sys.version_info >= (3, 8):
4+
from typing import Protocol
5+
else:
6+
from typing_extensions import Protocol
7+
8+
import jneqsim.api.ioc
9+
import typing
10+
11+
12+
class __module_protocol__(Protocol):
13+
# A module protocol which reflects the result of ``jp.JPackage("jneqsim.api")``.
14+
15+
ioc: jneqsim.api.ioc.__module_protocol__
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
import sys
3+
if sys.version_info >= (3, 8):
4+
from typing import Protocol
5+
else:
6+
from typing_extensions import Protocol
7+
8+
import java.lang
9+
import jpype
10+
import typing
11+
12+
13+
14+
class CalculationResult:
15+
fluidProperties: typing.MutableSequence[typing.MutableSequence[float]] = ...
16+
calculationError: typing.MutableSequence[java.lang.String] = ...
17+
def __init__(self, doubleArray: typing.Union[typing.List[typing.MutableSequence[float]], jpype.JArray], stringArray: typing.Union[typing.List[java.lang.String], jpype.JArray]): ...
18+
def equals(self, object: typing.Any) -> bool: ...
19+
def hashCode(self) -> int: ...
20+
21+
22+
class __module_protocol__(Protocol):
23+
# A module protocol which reflects the result of ``jp.JPackage("jneqsim.api.ioc")``.
24+
25+
CalculationResult: typing.Type[CalculationResult]
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
2+
import sys
3+
if sys.version_info >= (3, 8):
4+
from typing import Protocol
5+
else:
6+
from typing_extensions import Protocol
7+
8+
import java.util
9+
import jpype
10+
import jneqsim.blackoil.io
11+
import jneqsim.thermo.system
12+
import typing
13+
14+
15+
16+
class BlackOilConverter:
17+
def __init__(self): ...
18+
@staticmethod
19+
def convert(systemInterface: jneqsim.thermo.system.SystemInterface, double: float, doubleArray: typing.Union[typing.List[float], jpype.JArray], double3: float, double4: float) -> 'BlackOilConverter.Result': ...
20+
class Result:
21+
pvt: 'BlackOilPVTTable' = ...
22+
blackOilSystem: 'SystemBlackOil' = ...
23+
rho_o_sc: float = ...
24+
rho_g_sc: float = ...
25+
rho_w_sc: float = ...
26+
bubblePoint: float = ...
27+
def __init__(self): ...
28+
29+
class BlackOilFlash:
30+
def __init__(self, blackOilPVTTable: 'BlackOilPVTTable', double: float, double2: float, double3: float): ...
31+
def flash(self, double: float, double2: float, double3: float, double4: float, double5: float) -> 'BlackOilFlashResult': ...
32+
33+
class BlackOilFlashResult:
34+
O_std: float = ...
35+
Gf_std: float = ...
36+
W_std: float = ...
37+
V_o: float = ...
38+
V_g: float = ...
39+
V_w: float = ...
40+
rho_o: float = ...
41+
rho_g: float = ...
42+
rho_w: float = ...
43+
mu_o: float = ...
44+
mu_g: float = ...
45+
mu_w: float = ...
46+
Rs: float = ...
47+
Rv: float = ...
48+
Bo: float = ...
49+
Bg: float = ...
50+
Bw: float = ...
51+
def __init__(self): ...
52+
53+
class BlackOilPVTTable:
54+
def __init__(self, list: java.util.List['BlackOilPVTTable.Record'], double: float): ...
55+
def Bg(self, double: float) -> float: ...
56+
def Bo(self, double: float) -> float: ...
57+
def Bw(self, double: float) -> float: ...
58+
def Rs(self, double: float) -> float: ...
59+
def RsEffective(self, double: float) -> float: ...
60+
def Rv(self, double: float) -> float: ...
61+
def getBubblePointP(self) -> float: ...
62+
def mu_g(self, double: float) -> float: ...
63+
def mu_o(self, double: float) -> float: ...
64+
def mu_w(self, double: float) -> float: ...
65+
class Record:
66+
p: float = ...
67+
Rs: float = ...
68+
Bo: float = ...
69+
mu_o: float = ...
70+
Bg: float = ...
71+
mu_g: float = ...
72+
Rv: float = ...
73+
Bw: float = ...
74+
mu_w: float = ...
75+
def __init__(self, double: float, double2: float, double3: float, double4: float, double5: float, double6: float, double7: float, double8: float, double9: float): ...
76+
77+
class SystemBlackOil:
78+
def __init__(self, blackOilPVTTable: BlackOilPVTTable, double: float, double2: float, double3: float): ...
79+
def copyShallow(self) -> 'SystemBlackOil': ...
80+
def flash(self) -> BlackOilFlashResult: ...
81+
def getBg(self) -> float: ...
82+
def getBo(self) -> float: ...
83+
def getBw(self) -> float: ...
84+
def getGasDensity(self) -> float: ...
85+
def getGasReservoirVolume(self) -> float: ...
86+
def getGasStdTotal(self) -> float: ...
87+
def getGasViscosity(self) -> float: ...
88+
def getOilDensity(self) -> float: ...
89+
def getOilReservoirVolume(self) -> float: ...
90+
def getOilStdTotal(self) -> float: ...
91+
def getOilViscosity(self) -> float: ...
92+
def getPressure(self) -> float: ...
93+
def getRs(self) -> float: ...
94+
def getRv(self) -> float: ...
95+
def getTemperature(self) -> float: ...
96+
def getWaterDensity(self) -> float: ...
97+
def getWaterReservoirVolume(self) -> float: ...
98+
def getWaterStd(self) -> float: ...
99+
def getWaterViscosity(self) -> float: ...
100+
def setPressure(self, double: float) -> None: ...
101+
def setStdTotals(self, double: float, double2: float, double3: float) -> None: ...
102+
def setTemperature(self, double: float) -> None: ...
103+
104+
105+
class __module_protocol__(Protocol):
106+
# A module protocol which reflects the result of ``jp.JPackage("jneqsim.blackoil")``.
107+
108+
BlackOilConverter: typing.Type[BlackOilConverter]
109+
BlackOilFlash: typing.Type[BlackOilFlash]
110+
BlackOilFlashResult: typing.Type[BlackOilFlashResult]
111+
BlackOilPVTTable: typing.Type[BlackOilPVTTable]
112+
SystemBlackOil: typing.Type[SystemBlackOil]
113+
io: jneqsim.blackoil.io.__module_protocol__

0 commit comments

Comments
 (0)