topologicpy 0.7.23__py3-none-any.whl → 0.7.24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -91,7 +91,7 @@ class CellComplex():
91
91
  direction=direction, placement=placement, tolerance=tolerance)
92
92
 
93
93
  @staticmethod
94
- def ByCells(cells: list, tolerance: float = 0.0001, silent: bool = False):
94
+ def ByCells(cells: list, transferDictionaries = False, tolerance: float = 0.0001, silent: bool = False):
95
95
  """
96
96
  Creates a cellcomplex by merging the input cells.
97
97
 
@@ -99,6 +99,8 @@ class CellComplex():
99
99
  ----------
100
100
  cells : list
101
101
  The list of input cells.
102
+ transferDictionaries : bool , optional
103
+ If set to True, any dictionaries in the cells are transferred to the CellComplex. Otherwise, they are not. The default is False.
102
104
  tolerance : float , optional
103
105
  The desired tolerance. The default is 0.0001.
104
106
 
@@ -108,8 +110,10 @@ class CellComplex():
108
110
  The created cellcomplex.
109
111
 
110
112
  """
113
+ from topologicpy.Vertex import Vertex
111
114
  from topologicpy.Cluster import Cluster
112
115
  from topologicpy.Topology import Topology
116
+ from topologicpy.Dictionary import Dictionary
113
117
 
114
118
  if not isinstance(cells, list):
115
119
  if not silent:
@@ -120,6 +124,7 @@ class CellComplex():
120
124
  if not silent:
121
125
  print("CellComplex.ByCells - Error: The input cells parameter does not contain any valid cells. Returning None.")
122
126
  return None
127
+ cluster = Cluster.ByTopologies(cells)
123
128
  cellComplex = None
124
129
  if len(cells) == 1:
125
130
  return topologic.CellComplex.ByCells(cells) # Hook to Core
@@ -149,6 +154,14 @@ class CellComplex():
149
154
  if not silent:
150
155
  print("CellComplex.ByCells - Warning: Resulting object contains only one cell. Returning object of type topologic_core.Cell instead of topologic_core.CellComplex.")
151
156
  return(temp_cells[0])
157
+ if transferDictionaries == True:
158
+ for temp_cell in temp_cells:
159
+ v = Topology.InternalVertex(temp_cell)
160
+ enclosing_cells = Vertex.EnclosingCell(v, cluster)
161
+ dictionaries = [Topology.Dictionary(ec) for ec in enclosing_cells]
162
+ d = Dictionary.ByMergedDictionaries(dictionaries, silent=silent)
163
+ temp_cell = Topology.SetDictionary(temp_cell, d)
164
+
152
165
  return cellComplex
153
166
 
154
167
  @staticmethod
topologicpy/Cluster.py CHANGED
@@ -143,7 +143,7 @@ class Cluster():
143
143
  return Cluster.ByTopologies(vertices)
144
144
 
145
145
  @staticmethod
146
- def ByTopologies(*args, transferDictionaries: bool = False):
146
+ def ByTopologies(*args, transferDictionaries: bool = False, silent=False):
147
147
  """
148
148
  Creates a topologic Cluster from the input list of topologies. The input can be individual topologies each as an input argument or a list of topologies stored in one input argument.
149
149
 
@@ -153,7 +153,8 @@ class Cluster():
153
153
  The list of topologies.
154
154
  transferDictionaries : bool , optional
155
155
  If set to True, the dictionaries from the input topologies are merged and transferred to the cluster. Otherwise they are not. The default is False.
156
-
156
+ silent : bool , optional
157
+ If set to True, error and warning messages are not displayed. Otherwise, they are. The default is False.
157
158
  Returns
158
159
  -------
159
160
  topologic_core.Cluster
@@ -197,7 +198,7 @@ class Cluster():
197
198
  dictionaries.append(d)
198
199
  if len(dictionaries) > 0:
199
200
  if len(dictionaries) > 1:
200
- d = Dictionary.ByMergedDictionaries(dictionaries)
201
+ d = Dictionary.ByMergedDictionaries(dictionaries, silent=silent)
201
202
  else:
202
203
  d = dictionaries[0]
203
204
  cluster = Topology.SetDictionary(cluster, d)
topologicpy/Dictionary.py CHANGED
@@ -153,7 +153,7 @@ class Dictionary():
153
153
  return topologic.Dictionary.ByKeysValues(stl_keys, stl_values) # Hook to Core
154
154
 
155
155
  @staticmethod
156
- def ByMergedDictionaries(*dictionaries):
156
+ def ByMergedDictionaries(*dictionaries, silent: bool = False):
157
157
  """
158
158
  Creates a dictionary by merging the list of input dictionaries.
159
159
 
@@ -161,6 +161,8 @@ class Dictionary():
161
161
  ----------
162
162
  dictionaries : list or comma separated dictionaries
163
163
  The input list of dictionaries to be merged.
164
+ silent : bool , optional
165
+ If set to True, error and warning messages are not displayed. Otherwise, they are. The default is False.
164
166
 
165
167
  Returns
166
168
  -------
@@ -176,13 +178,16 @@ class Dictionary():
176
178
  if isinstance(dictionaries, list):
177
179
  new_dictionaries = [d for d in dictionaries if Topology.IsInstance(d, "Dictionary")]
178
180
  if len(new_dictionaries) == 0:
179
- print("Dictionary.ByMergedDictionaries - Error: the input dictionaries parameter does not contain any valid dictionaries. Returning None.")
181
+ if not silent:
182
+ print("Dictionary.ByMergedDictionaries - Error: the input dictionaries parameter does not contain any valid dictionaries. Returning None.")
180
183
  return None
181
184
  if len(new_dictionaries) == 1:
182
- print("Dictionary.ByMergedDictionaries - Error: the input dictionaries parameter contains only one dictionary. Returning input dictionary.")
185
+ if not silent:
186
+ print("Dictionary.ByMergedDictionaries - Error: the input dictionaries parameter contains only one dictionary. Returning input dictionary.")
183
187
  return new_dictionaries[0]
184
188
  if not isinstance(new_dictionaries, list):
185
- print("Dictionary.ByMergedDictionaries - Error: The input dictionaries parameter is not a valid list. Returning None.")
189
+ if not silent:
190
+ print("Dictionary.ByMergedDictionaries - Error: The input dictionaries parameter is not a valid list. Returning None.")
186
191
  return None
187
192
  return_dictionaries = []
188
193
  for d in new_dictionaries:
@@ -191,10 +196,12 @@ class Dictionary():
191
196
  elif isinstance(d, dict):
192
197
  return_dictionaries.append(Dictionary.ByPythonDictionary(d))
193
198
  if len(return_dictionaries) == 0:
194
- print("Dictionary.ByMergedDictionaries - Error: The input dictionaries parameter does not contain valid dictionaries. Returning None.")
199
+ if not silent:
200
+ print("Dictionary.ByMergedDictionaries - Error: The input dictionaries parameter does not contain valid dictionaries. Returning None.")
195
201
  return None
196
202
  elif len(return_dictionaries) == 1:
197
- print("Dictionary.ByMergedDictionaries - Warning: The input dictionaries parameter contains only one valid dictionary. Returning that dictionary.")
203
+ if not silent:
204
+ print("Dictionary.ByMergedDictionaries - Warning: The input dictionaries parameter contains only one valid dictionary. Returning that dictionary.")
198
205
  return new_dictionaries[0]
199
206
  else:
200
207
  dictionaries = return_dictionaries
topologicpy/Topology.py CHANGED
@@ -2443,7 +2443,6 @@ class Topology():
2443
2443
 
2444
2444
  def buildCell(json_item, j_shells, j_faces, j_wires, j_edges, j_vertices, uuidKey="uuid", tolerance=0.0001):
2445
2445
  cell_shells = json_item['shells']
2446
- shells = []
2447
2446
  external_boundary = buildShell(find_json_item(j_shells, uuidKey, cell_shells[0]), j_faces, j_wires, j_edges, j_vertices, uuidKey=uuidKey, tolerance=tolerance)
2448
2447
  internal_boundaries = []
2449
2448
  for j_s in cell_shells[1:]:
@@ -2468,7 +2467,7 @@ class Topology():
2468
2467
  cells = []
2469
2468
  for j_c in cc_cells:
2470
2469
  cells.append(buildCell(find_json_item(j_cells, uuidKey, j_c), j_shells, j_faces, j_wires, j_edges, j_vertices, uuidKey=uuidKey, tolerance=tolerance))
2471
- cc = CellComplex.ByCells(cells, tolerance=tolerance)
2470
+ cc = CellComplex.ByCells(cells, transferDictionaries=False, silent=True, tolerance=tolerance)
2472
2471
  if cc == None:
2473
2472
  print("Topology.ByJSONString - Error: Could not build a cellcomplex. Returning None.")
2474
2473
  return None
@@ -2645,18 +2644,10 @@ class Topology():
2645
2644
  d = Topology.Dictionary(ev)
2646
2645
  if Dictionary.ValueAtKey(d,'toplevel') == True:
2647
2646
  toplevelTopologies.append(ev)
2648
-
2647
+ return_topologies = []
2649
2648
  for tp in toplevelTopologies:
2650
2649
  # This is a hack because sometimes the imported topologies get weird. I think it is an opencascade bug.
2651
2650
  tp = Topology.ByBREPString(Topology.BREPString(tp))
2652
- if len(vertex_selectors) > 0:
2653
- _ = Topology.TransferDictionariesBySelectors(tp, vertex_selectors, tranVertices=True, tolerance=tolerance)
2654
- if len(edge_selectors) > 0:
2655
- _ = Topology.TransferDictionariesBySelectors(tp, edge_selectors, tranEdges=True, tolerance=tolerance)
2656
- if len(face_selectors) > 0:
2657
- _ = Topology.TransferDictionariesBySelectors(tp, face_selectors, tranFaces=True, tolerance=tolerance)
2658
- if len(cell_selectors) > 0:
2659
- _ = Topology.TransferDictionariesBySelectors(tp, cell_selectors, tranCells=True, tolerance=tolerance)
2660
2651
  if len(all_vertex_apertures) > 0:
2661
2652
  tp_vertices = Topology.Vertices(tp)
2662
2653
  for tp_vertex in tp_vertices:
@@ -2673,11 +2664,22 @@ class Topology():
2673
2664
  tp_cells = Topology.Cells(tp)
2674
2665
  for tp_cell in tp_cells:
2675
2666
  tp_cell = setApertures(tp_cell, all_cell_apertures, uuidKey="uuid")
2676
-
2677
- if len(toplevelTopologies) == 1:
2678
- return toplevelTopologies[0]
2667
+
2668
+ if len(vertex_selectors) > 0:
2669
+ _ = Topology.TransferDictionariesBySelectors(tp, vertex_selectors, tranVertices=True, tolerance=tolerance)
2670
+ if len(edge_selectors) > 0:
2671
+ _ = Topology.TransferDictionariesBySelectors(tp, edge_selectors, tranEdges=True, tolerance=tolerance)
2672
+ if len(face_selectors) > 0:
2673
+ _ = Topology.TransferDictionariesBySelectors(tp, face_selectors, tranFaces=True, tolerance=tolerance)
2674
+ if len(cell_selectors) > 0:
2675
+ _ = Topology.TransferDictionariesBySelectors(tp, cell_selectors, tranCells=True, tolerance=tolerance)
2676
+
2677
+ return_topologies.append(tp)
2678
+
2679
+ if len(return_topologies) == 1:
2680
+ return return_topologies[0]
2679
2681
  else:
2680
- return toplevelTopologies
2682
+ return return_topologies
2681
2683
 
2682
2684
  @staticmethod
2683
2685
  def ByJSONPath(path, tolerance=0.0001):
@@ -2711,7 +2713,7 @@ class Topology():
2711
2713
  defaultOpacity: float = 1.0,
2712
2714
  transposeAxes: bool = True,
2713
2715
  removeCoplanarFaces: bool = True,
2714
-
2716
+ selfMerge: bool = True,
2715
2717
  mantissa : int = 6,
2716
2718
  tolerance: float = 0.0001):
2717
2719
  """
@@ -2732,6 +2734,8 @@ class Topology():
2732
2734
  If set to True the Z and Y axes are transposed. Otherwise, they are not. The default is True.
2733
2735
  removeCoplanarFaces : bool , optional
2734
2736
  If set to True, coplanar faces are merged. The default is True.
2737
+ selfMerge : bool , optional
2738
+ If set to True, the faces of the imported topologies will each be self-merged to create higher-dimensional objects. Otherwise, they remain a cluster of faces. The default is False.
2735
2739
  mantissa : int , optional
2736
2740
  The desired length of the mantissa. The default is 6.
2737
2741
  tolerance : float , optional
@@ -2761,12 +2765,14 @@ class Topology():
2761
2765
  return Topology.ByOBJString(obj_string, mtl_string,
2762
2766
  defaultColor=defaultColor, defaultOpacity=defaultOpacity,
2763
2767
  transposeAxes=transposeAxes, removeCoplanarFaces=removeCoplanarFaces,
2768
+ selfMerge=selfMerge,
2764
2769
  mantissa=mantissa, tolerance=tolerance)
2765
2770
 
2766
2771
  @staticmethod
2767
2772
  def ByOBJPath(objPath,
2768
2773
  defaultColor: list = [255,255,255], defaultOpacity: float = 1.0,
2769
2774
  transposeAxes: bool = True, removeCoplanarFaces: bool = True,
2775
+ selfMerge: bool = False,
2770
2776
  mantissa : int = 6, tolerance: float = 0.0001):
2771
2777
  """
2772
2778
  Imports a topology from an OBJ file path and an associated materials file.
@@ -2784,6 +2790,8 @@ class Topology():
2784
2790
  If set to True the Z and Y axes are transposed. Otherwise, they are not. The default is True.
2785
2791
  removeCoplanarFaces : bool , optional
2786
2792
  If set to True, coplanar faces are merged. The default is True.
2793
+ selfMerge : bool , optional
2794
+ If set to True, the faces of the imported topologies will each be self-merged to create higher-dimensional objects. Otherwise, they remain a cluster of faces. The default is False.
2787
2795
  mantissa : int , optional
2788
2796
  The desired length of the mantissa. The default is 6.
2789
2797
  tolerance : float , optional
@@ -2824,12 +2832,14 @@ class Topology():
2824
2832
  return Topology.ByOBJString(obj_string, mtl_string,
2825
2833
  defaultColor=defaultColor, defaultOpacity=defaultOpacity,
2826
2834
  transposeAxes=transposeAxes, removeCoplanarFaces=removeCoplanarFaces,
2835
+ selfMerge = selfMerge,
2827
2836
  mantissa=mantissa, tolerance=tolerance)
2828
2837
 
2829
2838
  @staticmethod
2830
2839
  def ByOBJString(objString: str, mtlString: str = None,
2831
2840
  defaultColor: list = [255,255,255], defaultOpacity: float = 1.0,
2832
2841
  transposeAxes: bool = True, removeCoplanarFaces: bool = False,
2842
+ selfMerge: bool = False,
2833
2843
  mantissa = 6, tolerance = 0.0001):
2834
2844
  """
2835
2845
  Imports a topology from OBJ and MTL strings.
@@ -2848,6 +2858,8 @@ class Topology():
2848
2858
  If set to True the Z and Y axes are transposed. Otherwise, they are not. The default is True.
2849
2859
  removeCoplanarFaces : bool , optional
2850
2860
  If set to True, coplanar faces are merged. The default is True.
2861
+ selfMerge : bool , optional
2862
+ If set to True, the faces of the imported topologies will each be self-merged to create higher-dimensional objects. Otherwise, they remain a cluster of faces. The default is False.
2851
2863
  mantissa : int , optional
2852
2864
  The desired length of the mantissa. The default is 6.
2853
2865
  tolerance : float , optional
@@ -2994,7 +3006,9 @@ class Topology():
2994
3006
  selector = Topology.SetDictionary(selector, d)
2995
3007
  face_selectors.append(selector)
2996
3008
 
2997
- topology = Topology.SelfMerge(Cluster.ByTopologies(object_faces), tolerance=tolerance)
3009
+ topology = Cluster.ByTopologies(object_faces, tolerance=tolerance)
3010
+ if selfMerge:
3011
+ topology = Topology.SelfMerge(topology)
2998
3012
  if removeCoplanarFaces:
2999
3013
  topology = Topology.RemoveCoplanarFaces(topology, tolerance=tolerance)
3000
3014
  d = Dictionary.ByKeysValues(['name', 'color', 'opacity'], [object_name, object_color, object_opacity])
@@ -7599,6 +7613,10 @@ class Topology():
7599
7613
  The input topology with the dictionaries transferred to its subtopologies.
7600
7614
 
7601
7615
  """
7616
+ from topologicpy.Vertex import Vertex
7617
+ from topologicpy.Dictionary import Dictionary
7618
+ from topologicpy.Cluster import Cluster
7619
+ from topologicpy.Plotly import Plotly
7602
7620
  if not Topology.IsInstance(topology, "Topology"):
7603
7621
  print("Topology.TransferDictionariesBySelectors - Error: The input topology parameter is not a valid topology. Returning None.")
7604
7622
  return None
@@ -7639,10 +7657,11 @@ class Topology():
7639
7657
  _ = Topology.TransferDictionaries(selectors, sinkFaces, tolerance=tolerance, numWorkers=numWorkers)
7640
7658
  if tranCells == True:
7641
7659
  sinkCells = []
7642
- if Topology.Type(topology) == Topology.TypeID("Cell"):
7643
- sinkCells.append(topology)
7660
+ if Topology.IsInstance(topology, "Cell"):
7661
+ sinkCells = [topology]
7644
7662
  elif hidimSink >= Topology.TypeID("Cell"):
7645
- topology.Cells(None, sinkCells)
7663
+ print("Transfering Dictionaries to Cells")
7664
+ sinkCells = Topology.Cells(topology)
7646
7665
  _ = Topology.TransferDictionaries(selectors, sinkCells, tolerance=tolerance, numWorkers=numWorkers)
7647
7666
  return topology
7648
7667
 
topologicpy/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '0.7.23'
1
+ __version__ = '0.7.24'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: topologicpy
3
- Version: 0.7.23
3
+ Version: 0.7.24
4
4
  Summary: An Advanced Spatial Modelling and Analysis Software Library for Architecture, Engineering, and Construction.
5
5
  Author-email: Wassim Jabi <wassim.jabi@gmail.com>
6
6
  License: MIT License
@@ -1,12 +1,12 @@
1
1
  topologicpy/ANN.py,sha256=CLK6kPV28ag-hc60pyqoXt4GPiYQDUL8N48tjAbZ9Do,48981
2
2
  topologicpy/Aperture.py,sha256=p9pUzTQSBWoUaDiug1V1R1hnEIEwYSXFg2t7iRAmNRY,2723
3
3
  topologicpy/Cell.py,sha256=NjcKAqZywkr7DouYP4MGLhG6grWrXYfEpzDgUN-qAC0,99802
4
- topologicpy/CellComplex.py,sha256=-f-O5lcz0nSNcjw89XYi3IYhZRrbzojG11dItpISI_U,47401
5
- topologicpy/Cluster.py,sha256=6ZKtS82E2gCkX3oQKbx_aYL1GDiLYkleQbWWK5wYP7U,54815
4
+ topologicpy/CellComplex.py,sha256=x474N-lo1krpdIGrWRAFRdDup5a_1V-mLORTS6ZGZ7M,48227
5
+ topologicpy/Cluster.py,sha256=mwQVNXnh20VHms0ZqPzTROP8bUdVt8CTKtaNobAqHsE,54993
6
6
  topologicpy/Color.py,sha256=UlmRcCSOhqcM_OyMWz4t3Kr75KcgXDhz3uctAJ2n7Ic,18031
7
7
  topologicpy/Context.py,sha256=ppApYKngZZCQBFWaxIMi2z2dokY23c935IDCBosxDAE,3055
8
8
  topologicpy/DGL.py,sha256=Dd6O08D-vSxpjHYgKm45JpKiaeGvWlg1BRMzYMAXGNc,138991
9
- topologicpy/Dictionary.py,sha256=R6dqA2hqJX5t8faZmXCen8Cn3ukJ8VCHkyk-bune7-E,26770
9
+ topologicpy/Dictionary.py,sha256=4VtIT1p4UHWButzRUnajj16V0DY-d5RaENbXLNTbCYU,27097
10
10
  topologicpy/Edge.py,sha256=QHXb0R9bdPHfHhi64rXrCeeFoLv8iaMeBxqvocBm1XI,58327
11
11
  topologicpy/EnergyModel.py,sha256=ni0H1JgvLl1-q90yK9Sm1qj5P1fTuidlimEIcwuj6qE,53287
12
12
  topologicpy/Face.py,sha256=XS2ODccQRQvIdeuKAydjyAJmNqkwm8-RJJ5M1l4gt68,109523
@@ -21,14 +21,14 @@ topologicpy/Polyskel.py,sha256=4R5_DEdfrmi-4gR6axHNoHTCSAE2TCekOyN8jvb7bHQ,19722
21
21
  topologicpy/Shell.py,sha256=szuwRbQeHH9jd2X-DA9UhYAL_mzgfr_ctGrrQL2reWg,79917
22
22
  topologicpy/Speckle.py,sha256=rUS6PCaxIjEF5_fUruxvMH47FMKg-ohcoU0qAUb-yNM,14267
23
23
  topologicpy/Sun.py,sha256=_gZfVyH0SDLQmmt775UeeAJ_BtwXO1STQnUMV1qkU0s,37161
24
- topologicpy/Topology.py,sha256=EAu5bQl69c1n5KkJE1V2bapeEQsaCDL-ms0r-KzM35w,349215
24
+ topologicpy/Topology.py,sha256=OcNf5bZunNwLlJ8IiFPjcWmUBbtr3idgwYDazyBK4Pk,350515
25
25
  topologicpy/Vector.py,sha256=JAIeOZplh7sQD46K4eP3gMgvK6iB1wwpZ0sC9-FFGq8,32803
26
26
  topologicpy/Vertex.py,sha256=deOrCOvvGJYAludUE4Tm_L4Bx0ykQzO_ddnYSrUzsBs,71157
27
27
  topologicpy/Wire.py,sha256=_-0s6lFCStTGEjK5M-_w79UCQoPVFH1Ou8PdH_urvT0,145180
28
28
  topologicpy/__init__.py,sha256=D7ky87CAQMiS2KE6YLvcTLkTgA2PY7rASe6Z23pjp9k,872
29
- topologicpy/version.py,sha256=N6Bti6avPpwylwTGFsJIizCk0diNen56ql7y-MCAT6U,23
30
- topologicpy-0.7.23.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
31
- topologicpy-0.7.23.dist-info/METADATA,sha256=Km1K1jcxZhheChH715Z3gtb76475mzJZtqu-aJm2Y78,10916
32
- topologicpy-0.7.23.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
33
- topologicpy-0.7.23.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
34
- topologicpy-0.7.23.dist-info/RECORD,,
29
+ topologicpy/version.py,sha256=V0wSjRUUY2SPu2U3wOLkXUyScb5-aD_z0apG3LR4-SY,23
30
+ topologicpy-0.7.24.dist-info/LICENSE,sha256=BRNw73R2WdDBICtwhI3wm3cxsaVqLTAGuRwrTltcfxs,1068
31
+ topologicpy-0.7.24.dist-info/METADATA,sha256=C2gipIo8TAoRMeSosO1tXrLPkY5xPEiIprMpiku3JUI,10916
32
+ topologicpy-0.7.24.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
33
+ topologicpy-0.7.24.dist-info/top_level.txt,sha256=J30bDzW92Ob7hw3zA8V34Jlp-vvsfIkGzkr8sqvb4Uw,12
34
+ topologicpy-0.7.24.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.1.1)
2
+ Generator: setuptools (70.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5