cooptools 1.75__tar.gz → 1.76__tar.gz

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.
Files changed (191) hide show
  1. {cooptools-1.75 → cooptools-1.76}/PKG-INFO +1 -1
  2. {cooptools-1.75 → cooptools-1.76}/cooptools/common.py +4 -4
  3. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/vector_utils.py +39 -5
  4. {cooptools-1.75 → cooptools-1.76}/cooptools.egg-info/PKG-INFO +1 -1
  5. {cooptools-1.75 → cooptools-1.76}/setup.py +1 -1
  6. {cooptools-1.75 → cooptools-1.76}/tests/test_graph_node_classification.py +9 -6
  7. {cooptools-1.75 → cooptools-1.76}/MANIFEST.in +0 -0
  8. {cooptools-1.75 → cooptools-1.76}/README.md +0 -0
  9. {cooptools-1.75 → cooptools-1.76}/cooptools/__init__.py +0 -0
  10. {cooptools-1.75 → cooptools-1.76}/cooptools/anchor.py +0 -0
  11. {cooptools-1.75 → cooptools-1.76}/cooptools/asyncable.py +0 -0
  12. {cooptools-1.75 → cooptools-1.76}/cooptools/cli/CliAtomicUserInteraction.py +0 -0
  13. {cooptools-1.75 → cooptools-1.76}/cooptools/cli/CliMenu.py +0 -0
  14. {cooptools-1.75 → cooptools-1.76}/cooptools/cli/__init__.py +0 -0
  15. {cooptools-1.75 → cooptools-1.76}/cooptools/cli/fileContentReturn.py +0 -0
  16. {cooptools-1.75 → cooptools-1.76}/cooptools/cnxn_info.py +0 -0
  17. {cooptools-1.75 → cooptools-1.76}/cooptools/colors.py +0 -0
  18. {cooptools-1.75 → cooptools-1.76}/cooptools/commandDesignPattern/__init__.py +0 -0
  19. {cooptools-1.75 → cooptools-1.76}/cooptools/commandDesignPattern/commandController.py +0 -0
  20. {cooptools-1.75 → cooptools-1.76}/cooptools/commandDesignPattern/commandProtocol.py +0 -0
  21. {cooptools-1.75 → cooptools-1.76}/cooptools/commandDesignPattern/exceptions.py +0 -0
  22. {cooptools-1.75 → cooptools-1.76}/cooptools/config.py +0 -0
  23. {cooptools-1.75 → cooptools-1.76}/cooptools/coopDataclass.py +0 -0
  24. {cooptools-1.75 → cooptools-1.76}/cooptools/coopEnum.py +0 -0
  25. {cooptools-1.75 → cooptools-1.76}/cooptools/coopthreading.py +0 -0
  26. {cooptools-1.75 → cooptools-1.76}/cooptools/currency.py +0 -0
  27. {cooptools-1.75 → cooptools-1.76}/cooptools/dataRefresher/__init__.py +0 -0
  28. {cooptools-1.75 → cooptools-1.76}/cooptools/dataRefresher/dataHub.py +0 -0
  29. {cooptools-1.75 → cooptools-1.76}/cooptools/dataRefresher/dataRefresher.py +0 -0
  30. {cooptools-1.75 → cooptools-1.76}/cooptools/dataStore/__init__.py +0 -0
  31. {cooptools-1.75 → cooptools-1.76}/cooptools/dataStore/dataProcessor.py +0 -0
  32. {cooptools-1.75 → cooptools-1.76}/cooptools/dataStore/dataStoreProtocol.py +0 -0
  33. {cooptools-1.75 → cooptools-1.76}/cooptools/dataStore/dbConnectionURI.py +0 -0
  34. {cooptools-1.75 → cooptools-1.76}/cooptools/dataStore/inMemoryDataStore.py +0 -0
  35. {cooptools-1.75 → cooptools-1.76}/cooptools/date_utils.py +0 -0
  36. {cooptools-1.75 → cooptools-1.76}/cooptools/decay.py +0 -0
  37. {cooptools-1.75 → cooptools-1.76}/cooptools/decor.py +0 -0
  38. {cooptools-1.75 → cooptools-1.76}/cooptools/dictPolicies.py +0 -0
  39. {cooptools-1.75 → cooptools-1.76}/cooptools/exceptions.py +0 -0
  40. {cooptools-1.75 → cooptools-1.76}/cooptools/expertise/__init__.py +0 -0
  41. {cooptools-1.75 → cooptools-1.76}/cooptools/expertise/expertiseArgs.py +0 -0
  42. {cooptools-1.75 → cooptools-1.76}/cooptools/expertise/expertiseSchedules.py +0 -0
  43. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/__init__.py +0 -0
  44. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/dicounted_cashflow_analysis.py +0 -0
  45. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/fund_projection.py +0 -0
  46. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/fund_projection_renderer.py +0 -0
  47. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/futureValueProjector.py +0 -0
  48. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/growth_projections.py +0 -0
  49. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/reports.py +0 -0
  50. {cooptools-1.75 → cooptools-1.76}/cooptools/finance/utils.py +0 -0
  51. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/__init__.py +0 -0
  52. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/circle_utils.py +0 -0
  53. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/common.py +0 -0
  54. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/curve_utils.py +0 -0
  55. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/curves.py +0 -0
  56. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/line_utils.py +0 -0
  57. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/polygon_utils.py +0 -0
  58. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/rect_utils.py +0 -0
  59. {cooptools-1.75 → cooptools-1.76}/cooptools/geometry_utils/triangle_utils.py +0 -0
  60. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/__init__.py +0 -0
  61. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/astar_results_viewer.py +0 -0
  62. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/draw.py +0 -0
  63. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/flow_field.py +0 -0
  64. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/graph.py +0 -0
  65. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/graph_dcs.py +0 -0
  66. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/graph_definitions.py +0 -0
  67. {cooptools-1.75 → cooptools-1.76}/cooptools/graphs/utils.py +0 -0
  68. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/__init__.py +0 -0
  69. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/actionItemTracker/__init__.py +0 -0
  70. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/actionItemTracker/ai_tracker.py +0 -0
  71. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/actionItemTracker/dcs.py +0 -0
  72. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/discreteEventSimulator/__init__.py +0 -0
  73. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/discreteEventSimulator/discreteEventSimulator.py +0 -0
  74. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/jsonIO.py +0 -0
  75. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/metrics.py +0 -0
  76. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/triggerActionSystem/__init__.py +0 -0
  77. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/triggerActionSystem/signal.py +0 -0
  78. {cooptools-1.75 → cooptools-1.76}/cooptools/ideas/triggerActionSystem/trigger.py +0 -0
  79. {cooptools-1.75 → cooptools-1.76}/cooptools/loggingHelpers.py +0 -0
  80. {cooptools-1.75 → cooptools-1.76}/cooptools/marchingSquares.py +0 -0
  81. {cooptools-1.75 → cooptools-1.76}/cooptools/materialHandling/__init__.py +0 -0
  82. {cooptools-1.75 → cooptools-1.76}/cooptools/materialHandling/cli.py +0 -0
  83. {cooptools-1.75 → cooptools-1.76}/cooptools/materialHandling/dcs.py +0 -0
  84. {cooptools-1.75 → cooptools-1.76}/cooptools/materialHandling/selectionCriteria.py +0 -0
  85. {cooptools-1.75 → cooptools-1.76}/cooptools/matrixManipulation.py +0 -0
  86. {cooptools-1.75 → cooptools-1.76}/cooptools/os_manip.py +0 -0
  87. {cooptools-1.75 → cooptools-1.76}/cooptools/pandasHelpers.py +0 -0
  88. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/__init__.py +0 -0
  89. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/catmullRomFollower.py +0 -0
  90. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/demo/__init__.py +0 -0
  91. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/demo/server.py +0 -0
  92. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/kinematicGoalSeeker.py +0 -0
  93. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/motion_profile_utils.py +0 -0
  94. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/orbit_fuzzer.py +0 -0
  95. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/path_utils.py +0 -0
  96. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/straightLineFollower.py +0 -0
  97. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/trajectory_provider.py +0 -0
  98. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/waypoint.py +0 -0
  99. {cooptools-1.75 → cooptools-1.76}/cooptools/pathing/waypointFollower.py +0 -0
  100. {cooptools-1.75 → cooptools-1.76}/cooptools/physics/__init__.py +0 -0
  101. {cooptools-1.75 → cooptools-1.76}/cooptools/physics/kinematic.py +0 -0
  102. {cooptools-1.75 → cooptools-1.76}/cooptools/physics/kinematic_utils.py +0 -0
  103. {cooptools-1.75 → cooptools-1.76}/cooptools/physics/movement.py +0 -0
  104. {cooptools-1.75 → cooptools-1.76}/cooptools/physics/trajectory.py +0 -0
  105. {cooptools-1.75 → cooptools-1.76}/cooptools/plotting.py +0 -0
  106. {cooptools-1.75 → cooptools-1.76}/cooptools/printing.py +0 -0
  107. {cooptools-1.75 → cooptools-1.76}/cooptools/protocols.py +0 -0
  108. {cooptools-1.75 → cooptools-1.76}/cooptools/qualifiers/__init__.py +0 -0
  109. {cooptools-1.75 → cooptools-1.76}/cooptools/qualifiers/cli.py +0 -0
  110. {cooptools-1.75 → cooptools-1.76}/cooptools/qualifiers/qualifier.py +0 -0
  111. {cooptools-1.75 → cooptools-1.76}/cooptools/randoms.py +0 -0
  112. {cooptools-1.75 → cooptools-1.76}/cooptools/register.py +0 -0
  113. {cooptools-1.75 → cooptools-1.76}/cooptools/reservation/__init__.py +0 -0
  114. {cooptools-1.75 → cooptools-1.76}/cooptools/reservation/dcs.py +0 -0
  115. {cooptools-1.75 → cooptools-1.76}/cooptools/reservation/enums.py +0 -0
  116. {cooptools-1.75 → cooptools-1.76}/cooptools/reservation/reservationmanager.py +0 -0
  117. {cooptools-1.75 → cooptools-1.76}/cooptools/retry.py +0 -0
  118. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/__init__.py +0 -0
  119. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/grids/__init__.py +0 -0
  120. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/grids/gridState.py +0 -0
  121. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/grids/grid_base.py +0 -0
  122. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/grids/hexGrid.py +0 -0
  123. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/grids/rectGrid.py +0 -0
  124. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/hex_utils.py +0 -0
  125. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/sect_utils.py +0 -0
  126. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/sectorTree/__init__.py +0 -0
  127. {cooptools-1.75 → cooptools-1.76}/cooptools/sectors/sectorTree/sectorTree.py +0 -0
  128. {cooptools-1.75 → cooptools-1.76}/cooptools/statistics/__init__.py +0 -0
  129. {cooptools-1.75 → cooptools-1.76}/cooptools/statistics/activityReport.py +0 -0
  130. {cooptools-1.75 → cooptools-1.76}/cooptools/statistics/controlChart/__init__.py +0 -0
  131. {cooptools-1.75 → cooptools-1.76}/cooptools/statistics/controlChart/controlChart.py +0 -0
  132. {cooptools-1.75 → cooptools-1.76}/cooptools/statistics/controlChart/plotting.py +0 -0
  133. {cooptools-1.75 → cooptools-1.76}/cooptools/statistics/oee/__init__.py +0 -0
  134. {cooptools-1.75 → cooptools-1.76}/cooptools/statistics/oee/oeeHub.py +0 -0
  135. {cooptools-1.75 → cooptools-1.76}/cooptools/taskProcessing/__init__.py +0 -0
  136. {cooptools-1.75 → cooptools-1.76}/cooptools/taskProcessing/dcs.py +0 -0
  137. {cooptools-1.75 → cooptools-1.76}/cooptools/taskProcessing/taskProcessor.py +0 -0
  138. {cooptools-1.75 → cooptools-1.76}/cooptools/timeTracker/__init__.py +0 -0
  139. {cooptools-1.75 → cooptools-1.76}/cooptools/timeTracker/decay.py +0 -0
  140. {cooptools-1.75 → cooptools-1.76}/cooptools/timeTracker/timeTracker.py +0 -0
  141. {cooptools-1.75 → cooptools-1.76}/cooptools/timeWindow.py +0 -0
  142. {cooptools-1.75 → cooptools-1.76}/cooptools/toggles.py +0 -0
  143. {cooptools-1.75 → cooptools-1.76}/cooptools/transform.py +0 -0
  144. {cooptools-1.75 → cooptools-1.76}/cooptools/trends.py +0 -0
  145. {cooptools-1.75 → cooptools-1.76}/cooptools/typeProviders.py +0 -0
  146. {cooptools-1.75 → cooptools-1.76}/cooptools/typevalidation.py +0 -0
  147. {cooptools-1.75 → cooptools-1.76}/cooptools/version.py +0 -0
  148. {cooptools-1.75 → cooptools-1.76}/cooptools.egg-info/SOURCES.txt +0 -0
  149. {cooptools-1.75 → cooptools-1.76}/cooptools.egg-info/dependency_links.txt +0 -0
  150. {cooptools-1.75 → cooptools-1.76}/cooptools.egg-info/not-zip-safe +0 -0
  151. {cooptools-1.75 → cooptools-1.76}/cooptools.egg-info/requires.txt +0 -0
  152. {cooptools-1.75 → cooptools-1.76}/cooptools.egg-info/top_level.txt +0 -0
  153. {cooptools-1.75 → cooptools-1.76}/requirements.txt +0 -0
  154. {cooptools-1.75 → cooptools-1.76}/setup.cfg +0 -0
  155. {cooptools-1.75 → cooptools-1.76}/tests/test_CliAtomicUserInteraction.py +0 -0
  156. {cooptools-1.75 → cooptools-1.76}/tests/test_asyncable.py +0 -0
  157. {cooptools-1.75 → cooptools-1.76}/tests/test_catmullRomFollower.py +0 -0
  158. {cooptools-1.75 → cooptools-1.76}/tests/test_cdp_bugs.py +0 -0
  159. {cooptools-1.75 → cooptools-1.76}/tests/test_commandDesignPattern.py +0 -0
  160. {cooptools-1.75 → cooptools-1.76}/tests/test_common.py +0 -0
  161. {cooptools-1.75 → cooptools-1.76}/tests/test_config.py +0 -0
  162. {cooptools-1.75 → cooptools-1.76}/tests/test_coopEnum.py +0 -0
  163. {cooptools-1.75 → cooptools-1.76}/tests/test_currency.py +0 -0
  164. {cooptools-1.75 → cooptools-1.76}/tests/test_curves.py +0 -0
  165. {cooptools-1.75 → cooptools-1.76}/tests/test_date_utils.py +0 -0
  166. {cooptools-1.75 → cooptools-1.76}/tests/test_flow_field.py +0 -0
  167. {cooptools-1.75 → cooptools-1.76}/tests/test_flow_field_perf.py +0 -0
  168. {cooptools-1.75 → cooptools-1.76}/tests/test_fund_projection.py +0 -0
  169. {cooptools-1.75 → cooptools-1.76}/tests/test_kinematicGoalSeeker.py +0 -0
  170. {cooptools-1.75 → cooptools-1.76}/tests/test_kinematic_utils.py +0 -0
  171. {cooptools-1.75 → cooptools-1.76}/tests/test_os_manip.py +0 -0
  172. {cooptools-1.75 → cooptools-1.76}/tests/test_pandas.py +0 -0
  173. {cooptools-1.75 → cooptools-1.76}/tests/test_path_utils.py +0 -0
  174. {cooptools-1.75 → cooptools-1.76}/tests/test_printing.py +0 -0
  175. {cooptools-1.75 → cooptools-1.76}/tests/test_qualifiers.py +0 -0
  176. {cooptools-1.75 → cooptools-1.76}/tests/test_sectors.py +0 -0
  177. {cooptools-1.75 → cooptools-1.76}/tests/test_sectors_hex.py +0 -0
  178. {cooptools-1.75 → cooptools-1.76}/tests/test_sectors_sectorTree.py +0 -0
  179. {cooptools-1.75 → cooptools-1.76}/tests/test_statistics.py +0 -0
  180. {cooptools-1.75 → cooptools-1.76}/tests/test_straightLineFollower.py +0 -0
  181. {cooptools-1.75 → cooptools-1.76}/tests/test_target_seek.py +0 -0
  182. {cooptools-1.75 → cooptools-1.76}/tests/test_tasks.py +0 -0
  183. {cooptools-1.75 → cooptools-1.76}/tests/test_toggles.py +0 -0
  184. {cooptools-1.75 → cooptools-1.76}/tests/test_trajectory.py +0 -0
  185. {cooptools-1.75 → cooptools-1.76}/tests/test_trends.py +0 -0
  186. {cooptools-1.75 → cooptools-1.76}/tests/test_typevalidation.py +0 -0
  187. {cooptools-1.75 → cooptools-1.76}/tests/test_vector_utils.py +0 -0
  188. {cooptools-1.75 → cooptools-1.76}/tests/test_version.py +0 -0
  189. {cooptools-1.75 → cooptools-1.76}/tests/test_waypointFollower.py +0 -0
  190. {cooptools-1.75 → cooptools-1.76}/tests/tests_graph.py +0 -0
  191. {cooptools-1.75 → cooptools-1.76}/tests/tests_gridsystem.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cooptools
3
- Version: 1.75
3
+ Version: 1.76
4
4
  Summary: Generic Tooling
5
5
  Home-page: https://github.com/tylertjburns/cooptools
6
6
  Author: tburns
@@ -1,6 +1,6 @@
1
1
  import math
2
2
  import uuid
3
- from typing import List, Union, Tuple, Iterable, Callable, Sequence, TypeVar, Dict
3
+ from typing import List, Union, Tuple, Iterable, Callable, Sequence, TypeVar, Dict, Optional
4
4
  import itertools
5
5
  import numpy as np
6
6
  import bisect
@@ -145,12 +145,12 @@ def verify_unique(lst: Iterable, error_msg: str = None):
145
145
  def verify_len_match(iterable1,
146
146
  iterable2,
147
147
  error_msg: str = None,
148
- block:bool = True):
148
+ block:bool = True) -> Optional[int]:
149
149
  # Length is compared before the message is built. This sits under
150
150
  # rect_contains_point on the sector-tree insert path, where formatting a
151
151
  # message for a check that passes costs more than the check itself.
152
- if len(iterable1) == len(iterable2):
153
- return
152
+ if (l1:=len(iterable1)) == len(iterable2):
153
+ return l1
154
154
 
155
155
  msg = f"{iterable1} and {iterable2} do not have the same length ({len(iterable1)} vs {len(iterable2)})"
156
156
  verify(lambda: False, msg, error_msg, block=block)
@@ -108,12 +108,30 @@ def vector_between(start: FloatVec,
108
108
  allow_diff_lengths: bool = False
109
109
  ) -> FloatVec:
110
110
  if not allow_diff_lengths:
111
- verify_len_match(start, end)
111
+ l_start = verify_len_match(start, end)
112
+ l_end = l_start
113
+ else:
114
+ l_start, l_end = len(start), len(end)
115
+
116
+ # 2- and 3-D vectors are most of the traffic here, and for them the loop
117
+ # below costs far more than the subtractions it performs: a range, two
118
+ # bounds-checked conditionals per axis, a list append per axis, and a
119
+ # tuple() at the end. Naming the axes skips all of it.
120
+ #
121
+ # Equal lengths are part of the condition because that is the only case in
122
+ # which the loop's padding cannot apply; an unequal pair falls through and
123
+ # is padded or truncated exactly as before.
124
+ if l_start == l_end == 2:
125
+ return (end[0] - start[0], end[1] - start[1])
126
+
127
+ if l_start == l_end == 3:
128
+ return (end[0] - start[0], end[1] - start[1], end[2] - start[2])
112
129
 
113
130
  ret = []
114
- for idx in range(len(start)):
115
- e = end[idx] if idx < len(end) else 0
116
- s = start[idx] if idx < len(start) else 0
131
+
132
+ for idx in range(l_start):
133
+ e = end[idx] if idx < l_end else 0
134
+ s = start[idx] if idx < l_start else 0
117
135
 
118
136
  ret.append((e - s))
119
137
 
@@ -175,7 +193,23 @@ def scale_vector_length(a: FloatVec, scale: float) -> FloatVec:
175
193
 
176
194
 
177
195
  def vector_len(a: FloatVec, squared: bool = False) -> float:
178
- sum_sq = sum(ii ** 2 for ii in a)
196
+ # 2- and 3-D vectors are most of the traffic here, and for them the general
197
+ # branch spends more on interpreter overhead than on arithmetic: a generator
198
+ # object plus one resumption of it per axis, driven by sum(). Naming the
199
+ # axes skips both.
200
+ #
201
+ # sum() applies compensated (Neumaier) summation to floats, so for three
202
+ # terms it can land a ULP away from the plain addition used here. That
203
+ # difference is accepted: a ULP sits far below the precision a caller of a
204
+ # vector length can meaningfully rely on.
205
+ len_a = len(a)
206
+ if len_a == 2:
207
+ sum_sq = a[0] * a[0] + a[1] * a[1]
208
+ elif len_a == 3:
209
+ sum_sq = a[0] * a[0] + a[1] * a[1] + a[2] * a[2]
210
+ else:
211
+ sum_sq = sum(ii * ii for ii in a)
212
+
179
213
  return sum_sq if squared else math.sqrt(sum_sq)
180
214
 
181
215
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cooptools
3
- Version: 1.75
3
+ Version: 1.76
4
4
  Summary: Generic Tooling
5
5
  Home-page: https://github.com/tylertjburns/cooptools
6
6
  Author: tburns
@@ -7,7 +7,7 @@ with open('requirements.txt') as f:
7
7
  requirements = f.read().splitlines()
8
8
 
9
9
  setuptools.setup(name='cooptools',
10
- version='1.75',
10
+ version='1.76',
11
11
  description='Generic Tooling',
12
12
  url='https://github.com/tylertjburns/cooptools',
13
13
  author='tburns',
@@ -115,11 +115,16 @@ class TestAStarIgnoredDisablers(unittest.TestCase):
115
115
 
116
116
  class TestVerifyLenMatch(unittest.TestCase):
117
117
 
118
- def test_matching_lengths_pass_silently(self):
119
- self.assertIsNone(verify_len_match((1, 2), (3, 4)))
118
+ def test_matching_lengths_return_the_shared_length(self):
119
+ # The length is handed back so callers that need it -- vector_between
120
+ # being the reason -- do not have to measure the operands again.
121
+ self.assertEqual(2, verify_len_match((1, 2), (3, 4)))
120
122
 
121
- def test_two_empties_match(self):
122
- self.assertIsNone(verify_len_match((), ()))
123
+ def test_two_empties_match_and_report_zero(self):
124
+ self.assertEqual(0, verify_len_match((), ()))
125
+
126
+ def test_mismatch_returns_nothing_when_not_blocking(self):
127
+ self.assertIsNone(verify_len_match((1, 2, 3), (4, 5), block=False))
123
128
 
124
129
  def test_mismatched_lengths_raise(self):
125
130
  with self.assertRaises(ValueError):
@@ -131,8 +136,6 @@ class TestVerifyLenMatch(unittest.TestCase):
131
136
  self.assertIn('3', str(ctx.exception))
132
137
  self.assertIn('2', str(ctx.exception))
133
138
 
134
- def test_mismatch_does_not_raise_when_not_blocking(self):
135
- self.assertIsNone(verify_len_match((1, 2, 3), (4, 5), block=False))
136
139
 
137
140
 
138
141
  if __name__ == '__main__':
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes