# ***************************************************************************** # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # See NOTICE file for details. # # ***************************************************************************** """ JPype Beans Module ------------------ This customizer finds all occurences of methods with get or set and converts them into Python properties. This behavior is sometimes useful in programming with JPype with interactive shells, but also leads to a lot of confusion. Is this class exposing a variable or is this a property added JPype. As an unnecessary behavior that violates both the Python principle *"There should be one-- and preferably only one --obvious way to do it."* and the C++ principle *"You only pay for what you use"*. This misfeature was removed from the distribution as a default. However, given that it is useful to have methods appear as properties, it was moved to a an optional module. To use beans as properties: .. code-block:: python import jpype.beans The beans property modification is a global behavior and applies retroactively to all classes currently loaded. Once started it can not be undone. """ import _jpype from . import _jcustomizer from ._pykeywords import pysafe as _pysafe def _extract_accessor_pairs(members): """Extract pairs of corresponding property access methods (getter and setter) from a Java class's members (attributes). If a public method with a property's name exists no pair for that property will be extracted. Returns a dictionary with the property name as key and a tuple of (getter method, setter method) as value. A tuple element value might be `None` if only a getter or only a setter exists. """ accessor_pairs = {} for name, member in members.items(): if not isinstance(member, _jpype._JMethod) or len(name) <= 3: continue if name == "getClass": continue if member._isBeanAccessor(): property_name = name[3].lower() + name[4:] try: pair = accessor_pairs[property_name] pair[0] = member except KeyError: accessor_pairs[property_name] = [member, None] elif member._isBeanMutator(): property_name = name[3].lower() + name[4:] try: pair = accessor_pairs[property_name] pair[1] = member except KeyError: accessor_pairs[property_name] = [None, member] return accessor_pairs @_jcustomizer.JImplementationFor("java.lang.Object") class _BeansCustomizer(object): """ Add properties for get/set Bean patterns found in classes. """ def __jclass_init__(self): accessor_pairs = _extract_accessor_pairs(self.__dict__) for attr_name, (getter, setter) in accessor_pairs.items(): attr_name = _pysafe(attr_name) # Don't mess with an existing member if attr_name is None or attr_name in self.__dict__: continue # Add the property self._customize(attr_name, property(getter, setter))