Closed jdanceze closed 1 year ago
But, when changing the way to import as following, it can work.
from numpy import array
def gen_array(value):
return array(value)
So, how can I make pynguin to work when using the normal import
statement?
Sorry for the late reply. I've only found the time now to investigate on this issue.
The reason why your first example fails while your second one runs successfully lies in how the Python import system (and our module analysis in Pynguin) work: when you do import numpy as np
, Python imports the module numpy/__init__.py
, which itself imports a huge amount of code from the NumPy library. Using from numpy import array
imports only the array
function from NumPy.
Our module analysis now takes all imported code and analyses it. In the first case, it attempts to analyse a huge amount of NumPy code (everything transitively included by numpy/__init__.py
); in the second case, it attemts to only analyse the array
function.
The latter case works fine, as you've already mentioned. The former case, however, fails when Pynguin tries to retrieve the function's signature data using Python's inspect
library. I am not sure, why exactly this happens. From what I've seen is that the inspect
library considers the where
function from NumPy to be a built-in (maybe it is a function that is implemented in C? I am not familiar with the NumPy code base, thus I do not know). Retrieving the signature from a builtin function is not possible for the inspect
library, thus it raises the ValueError
that you've reported in the first place.
So, what can you do about this? Unfortunately, not too much. We need to carefully consider, whether we can just catch the particular exception, without breaking any other functionality regarding our module analysis. This might only be addressed in some future version of Pynguin. For now, the only thing you could do is using the from numpy import array
version.
Similar issue for pandas:
from pandas import DataFrame
def create_date_column_from_shipyear_shipmonth(df: DataFrame, date_col_name):
print("hi")
The traceback I get is
[14:33:14] INFO Start Pynguin Test Generation… generator.py:108
INFO Collecting static constants from module under test generator.py:210
INFO No constants found generator.py:213
INFO Setting up runtime collection of constants generator.py:222
[14:33:19] INFO Stop Pynguin Test Generation… generator.py:111
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /Users/sergei.issaev/anaconda3/envs/burn/bin/pynguin:8 in <module> │
│ │
│ 5 from pynguin.cli import main │
│ 6 if __name__ == '__main__': │
│ 7 │ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) │
│ ❱ 8 │ sys.exit(main()) │
│ 9 │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/cli.py:193 in main │
│ │
│ 190 │ set_configuration(parsed.config) │
│ 191 │ if console is not None: │
│ 192 │ │ with console.status("Running Pynguin..."): │
│ ❱ 193 │ │ │ return run_pynguin().value │
│ 194 │ else: │
│ 195 │ │ return run_pynguin().value │
│ 196 │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/generator.py:109 │
│ in run_pynguin │
│ │
│ 106 │ """ │
│ 107 │ try: │
│ 108 │ │ _LOGGER.info("Start Pynguin Test Generation…") │
│ ❱ 109 │ │ return _run() │
│ 110 │ finally: │
│ 111 │ │ _LOGGER.info("Stop Pynguin Test Generation…") │
│ 112 │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/generator.py:508 │
│ in _run │
│ │
│ 505 │
│ 506 │
│ 507 def _run() -> ReturnCode: │
│ ❱ 508 │ if (setup_result := _setup_and_check()) is None: │
│ 509 │ │ return ReturnCode.SETUP_FAILED │
│ 510 │ executor, test_cluster, constant_provider = setup_result │
│ 511 │ # traces slices for test cases after execution │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/generator.py:260 │
│ in _setup_and_check │
│ │
│ 257 │ │
│ 258 │ # Analyzing the SUT should not cause any coverage. │
│ 259 │ tracer.disable() │
│ ❱ 260 │ if (test_cluster := _setup_test_cluster()) is None: │
│ 261 │ │ return None │
│ 262 │ tracer.enable() │
│ 263 │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/generator.py:115 │
│ in _setup_test_cluster │
│ │
│ 112 │
│ 113 │
│ 114 def _setup_test_cluster() -> ModuleTestCluster | None: │
│ ❱ 115 │ test_cluster = generate_test_cluster( │
│ 116 │ │ config.configuration.module_name, │
│ 117 │ │ config.configuration.type_inference.type_inference_strategy, │
│ 118 │ │ query_type4py=config.configuration.type_inference.type4py, │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/module.py │
│ :1441 in generate_test_cluster │
│ │
│ 1438 │ Returns: │
│ 1439 │ │ A new test cluster for the given module │
│ 1440 │ """ │
│ ❱ 1441 │ return analyse_module( │
│ 1442 │ │ parse_module(module_name, query_type4py=query_type4py), │
│ 1443 │ │ type_inference_strategy, │
│ 1444 │ │ query_type4py=query_type4py, │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/module.py │
│ :1417 in analyse_module │
│ │
│ 1414 │ │ A test cluster for the module │
│ 1415 │ """ │
│ 1416 │ test_cluster = ModuleTestCluster(linenos=parsed_module.linenos) │
│ ❱ 1417 │ __resolve_dependencies( │
│ 1418 │ │ root_module=parsed_module, │
│ 1419 │ │ type_inference_strategy=type_inference_strategy, │
│ 1420 │ │ test_cluster=test_cluster, │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/module.py │
│ :1290 in __resolve_dependencies │
│ │
│ 1287 │ │ │ continue │
│ 1288 │ │ │
│ 1289 │ │ # Analyze all classes found in the current module │
│ ❱ 1290 │ │ __analyse_included_classes( │
│ 1291 │ │ │ module=current_module, │
│ 1292 │ │ │ root_module_name=root_module.module_name, │
│ 1293 │ │ │ type_inference_strategy=type_inference_strategy, │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/module.py │
│ :1350 in __analyse_included_classes │
│ │
│ 1347 │ │ │
│ 1348 │ │ type_info = test_cluster.type_system.to_type_info(current) │
│ 1349 │ │ │
│ ❱ 1350 │ │ __analyse_class( │
│ 1351 │ │ │ type_info=type_info, │
│ 1352 │ │ │ type_inference_strategy=type_inference_strategy, │
│ 1353 │ │ │ module_tree=parse_results[current.__module__].syntax_tree, │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/module.py │
│ :1140 in __analyse_class │
│ │
│ 1137 │ for method_name, method in inspect.getmembers( │
│ 1138 │ │ type_info.raw_type, inspect.isfunction │
│ 1139 │ ): │
│ ❱ 1140 │ │ __analyse_method( │
│ 1141 │ │ │ type_info=type_info, │
│ 1142 │ │ │ method_name=method_name, │
│ 1143 │ │ │ method=method, │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/module.py │
│ :1212 in __analyse_method │
│ │
│ 1209 │ │ return │
│ 1210 │ │
│ 1211 │ LOGGER.debug("Analysing method %s.%s", type_info.full_name, method_name) │
│ ❱ 1212 │ inferred_signature = test_cluster.type_system.infer_type_info( │
│ 1213 │ │ method, │
│ 1214 │ │ type4py_data=find_predicted_signature( │
│ 1215 │ │ │ type4py_data, type_info.qualname + "." + method_name, type_info.qualname │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/typesyste │
│ m.py:1517 in infer_type_info │
│ │
│ 1514 │ │ """ │
│ 1515 │ │ match type_inference_strategy: │
│ 1516 │ │ │ case config.TypeInferenceStrategy.TYPE_HINTS: │
│ ❱ 1517 │ │ │ │ return self.infer_signature( │
│ 1518 │ │ │ │ │ method, type4py_data, self.type_hints_provider │
│ 1519 │ │ │ │ ) │
│ 1520 │ │ │ case config.TypeInferenceStrategy.NONE: │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/typesyste │
│ m.py:1580 in infer_signature │
│ │
│ 1577 │ │ │ The inference result │
│ 1578 │ │ """ │
│ 1579 │ │ method_signature = inspect.signature(method) │
│ ❱ 1580 │ │ hints = type_hint_provider(method) │
│ 1581 │ │ parameters: dict[str, ProperType] = {} │
│ 1582 │ │ type4py_parameters: dict[str, list[ProperType]] = {} │
│ 1583 │ │ type4py_parameters_for_statistics: dict[str, list[ProperType]] = {} │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/site-packages/pynguin/analyses/typesyste │
│ m.py:1552 in type_hints_provider │
│ │
│ 1549 │ │ │ A dict mapping parameter names to type hints. │
│ 1550 │ │ """ │
│ 1551 │ │ try: │
│ ❱ 1552 │ │ │ hints = get_type_hints(method) │
│ 1553 │ │ │ # Sadly there is no guarantee that resolving the type hints actually works. │
│ 1554 │ │ │ # If the developers annotated something with an erroneous type hint we fall │
│ 1555 │ │ │ # back to no type hints, i.e., use Any. │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/typing.py:1836 in get_type_hints │
│ │
│ 1833 │ │ │ value = type(None) │
│ 1834 │ │ if isinstance(value, str): │
│ 1835 │ │ │ value = ForwardRef(value) │
│ ❱ 1836 │ │ value = _eval_type(value, globalns, localns) │
│ 1837 │ │ if name in defaults and defaults[name] is None: │
│ 1838 │ │ │ value = Optional[value] │
│ 1839 │ │ hints[name] = value │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/typing.py:324 in _eval_type │
│ │
│ 321 │ with recursive ForwardRef. │
│ 322 │ """ │
│ 323 │ if isinstance(t, ForwardRef): │
│ ❱ 324 │ │ return t._evaluate(globalns, localns, recursive_guard) │
│ 325 │ if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)): │
│ 326 │ │ ev_args = tuple(_eval_type(a, globalns, localns, recursive_guard) for a in t.__a │
│ 327 │ │ if ev_args == t.__args__: │
│ │
│ /Users/sergei.issaev/anaconda3/envs/burn/lib/python3.10/typing.py:688 in _evaluate │
│ │
│ 685 │ │ │ │ │ sys.modules.get(self.__forward_module__, None), '__dict__', globalns │
│ 686 │ │ │ │ ) │
│ 687 │ │ │ type_ =_type_check( │
│ ❱ 688 │ │ │ │ eval(self.__forward_code__, globalns, localns), │
│ 689 │ │ │ │ "Forward references must evaluate to types.", │
│ 690 │ │ │ │ is_argument=self.__forward_is_argument__, │
│ 691 │ │ │ ) │
│ in <module>:1 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AttributeError: 'NoneType' object has no attribute 'DTypeLike'
I've just released Pynguin 0.33.0, which should fix the issue. I assume that this is only a partial fault of Pynguin—we are querying get_type_hints
from Python's typing
library, which raises the exception. Maybe, we are doing something wrong...
@stephanlukasczyk in pynguin 0.34.0 i still get
ValueError: no signature found for builtin <slot wrapper '__init__' of 'pyarrow.lib.ExtensionType' objects>
for:
import pyarrow as pa, pyarrow.parquet as pq
also get
ModuleNotFoundError: No module named '_regex'```
Do you have a full MRE for me, @tooptoop4 , please? That is, source file, required dependencies plus their versions, Pynguin command line, etc. Otherwise, it's hard to debug things and come up with a fix.
I try to run pynguin to generate the test case for this example module (
numpy_example
) containing the following snippet.but i got an error as
ValueError: no signature found for builtin <built-in function where>
This is the full stack trace.