1# Copyright 2020, 2021 PaGMO development team
2#
3# This file is part of the pygmo library.
4#
5# This Source Code Form is subject to the terms of the Mozilla
6# Public License v. 2.0. If a copy of the MPL was not distributed
7# with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
9from .core import topology
10
11
12def _topology_extract(self, t):
13    """Extract the user-defined topology.
14
15    This method allows to extract a reference to the user-defined topology (UDT) stored within this
16    :class:`~pygmo.topology` instance. The behaviour of this function depends on the value
17    of *t* (which must be a :class:`type`) and on the type of the internal UDT:
18
19    * if the type of the UDT is *t*, then a reference to the UDT will be returned
20      (this mirrors the behaviour of the corresponding C++ method
21      :cpp:func:`pagmo::topology::extract()`),
22    * if *t* is :class:`object` and the UDT is a Python object (as opposed to an
23      :ref:`exposed C++ topology <topologies_cpp>`), then a reference to the
24      UDT will be returned (this allows to extract a Python UDT without knowing its type),
25    * otherwise, :data:`None` will be returned.
26
27    Args:
28        t (:class:`type`): the type of the user-defined topology to extract
29
30    Returns:
31        a reference to the internal user-defined topology, or :data:`None` if the extraction fails
32
33    Raises:
34        TypeError: if *t* is not a :class:`type`
35
36    Examples:
37        >>> import pygmo as pg
38        >>> t1 = pg.topology(pg.ring())
39        >>> t1.extract(pg.ring) # doctest: +SKIP
40        <pygmo.core.ring at 0x7f8e4792b670>
41        >>> t1.extract(pg.unconnected) is None
42        True
43        >>> class topo:
44        ...     def get_connections(self, n):
45        ...         return [[], []]
46        ...     def push_back(self):
47        ...         return
48        >>> t2 = pg.topology(topo())
49        >>> t2.extract(object) # doctest: +SKIP
50        <__main__.topo at 0x7f8e478c04e0>
51        >>> t2.extract(topo) # doctest: +SKIP
52        <__main__.topo at 0x7f8e478c04e0>
53        >>> t2.extract(pg.unconnected) is None
54        True
55
56    """
57    if not isinstance(t, type):
58        raise TypeError("the 't' parameter must be a type")
59    if hasattr(t, "_pygmo_cpp_topology"):
60        return self._cpp_extract(t())
61    return self._py_extract(t)
62
63
64def _topology_is(self, t):
65    """Check the type of the user-defined topology.
66
67    This method returns :data:`False` if :func:`extract(t) <pygmo.topology.extract>` returns
68    :data:`None`, and :data:`True` otherwise.
69
70    Args:
71        t (:class:`type`): the type that will be compared to the type of the UDT
72
73    Returns:
74        bool: whether the UDT is of type *t* or not
75
76    Raises:
77        unspecified: any exception thrown by :func:`~pygmo.topology.extract()`
78
79    """
80    return not self.extract(t) is None
81
82
83# Do the actual patching.
84setattr(topology, "extract", _topology_extract)
85setattr(topology, "is_", _topology_is)
86