You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Jul 17, 2024. It is now read-only.
chore: Remove old wrapper generation code and use more Pythonic API (#23)
This refactor remove the old wrapper generation code (which was used to
add annotations to fields) and uses the new jpyinterpreter API to add
annotations to the fields instead. As a result, the following was able
to be removed:
- The Python specific solution cloner.
- The Python specific wrappers of Comparable and List.
- The methods in the timefold-solver-python-core module
used to add annotations and cloning methods.
- JPype auto-conversions for PythonLikeObject and Comparable
Additionally, the API and annotations where refactored to be more
Pythonic. For instance,
```python
class A:
@planning_variable(int)
def get_x():
return x
```
becomes
```python
class A:
x: Annotated[int, PlanningVariable]
```
and
```python
solver_config = \
SolverConfig().withSolutionClass(...).withEntityClasses(...)
solver = solver_factory_create(solver_config).buildSolver()
```
becomes
```python
solver_config = SolverConfig(
solution_class=SolutionClass,
entity_classes=[EntityClass],
...)
solver = SolverFactory.create(solver_config).build_solver()
```
This process also uncovered several bugs in jpyinterpreter:
- Method dispatchers for JavaObjectWrapper were not registered correctly
- The jpyinterpreter objects do not know if they were clone, so they
reuse the existing python references (since Timefold just treat it
as a regular shallowly cloned field). A ConcurrentWeakIdentityHashMap
is used to detect if the object was cloned and thus should create a
new instance.
- The ArgumentSpec field was not created for wrapped functions, which caused
an issue for UUID.__init__
- Apparently UUID was self-referencing, meaning the globals
map for its module had null in it since we put a None
in the type dict to prevent infinite recursion
- Now we create an "incomplete" type that we put inside the
dict before superclasses/methods/fields are processed, and
the type is filled in when the class is finally compiled.
- Fix call to old method in Python code that was replaced by a
BuiltinTypes field.
- tuple comparision methods were missing
- Added an exit handler to conftest that exits the JVM
so PyTest does not hang from daemon thread (and allows
us to remove the sleep call)
The tests also had several typing errors which are now fixed.
Additionally, no more extremely unuseful error message with generic
advice; the stack trace is now preserved for non-signal exceptions
(cause, Python really likes using exceptions in it bytecode; whenever
you do a for-loop, that actually a
`try { while True {...} } catch(StopIteration) {}` block).
As a side-effect, if no best solution listener is registered, the
code never returns to Python until Solving finishes (before,
it returned to Python on each new best solution).
To allow Timefold Solver to use the class object generated by jpyinterpreter,
several changes need to be made:
- Fields can now actually use generic, so List[int] become
List[PythonLikeInteger] in the bytecode
- Added a proxy generator for functions and classes. The
proxy generator for functions create a class that just
call a fixed instance of the function (since functions
might have closures which are specific to an instance).
The proxy generator for classes create a class that
creates a delegate to the class in the constructor
and delegate all calls to that delegate.
- Since PythonLikeBoolean is not a boolean (since it
need to support all Python operations), changed
PlanningPin so it is read in the entity's pinning
filter.
The following two features are currently unsupported in this version:
- ConstraintMatches in incremental score calculator. Requires changes
to the unwrapping code so the items in the List are unwrapped.
- ProblemChanges
Additionally, upgraded min version to Python 3.10, since numpy
no longers support Python 3.9
(https://numpy.org/neps/nep-0029-deprecation_policy.html) and
the scientific python community also recommends dropping support
for Python 3.9 since the start of this year
(https://scientific-python.org/specs/spec-0000/).
0 commit comments