salabim 25.0.3__py3-none-any.whl → 25.0.6__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.
- salabim/salabim.py +90 -32
- {salabim-25.0.3.dist-info → salabim-25.0.6.dist-info}/METADATA +1 -1
- {salabim-25.0.3.dist-info → salabim-25.0.6.dist-info}/RECORD +5 -5
- {salabim-25.0.3.dist-info → salabim-25.0.6.dist-info}/WHEEL +1 -1
- {salabim-25.0.3.dist-info → salabim-25.0.6.dist-info}/top_level.txt +0 -0
salabim/salabim.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
# _ _ _ ____ ____ ___
|
2
|
-
# ___ __ _ | | __ _ | |__ (_) _ __ ___ |___ \ | ___| / _ \
|
3
|
-
# / __| / _` || | / _` || '_ \ | || '_ ` _ \ __) ||___ \ | | | |
|
4
|
-
# \__ \| (_| || || (_| || |_) || || | | | | | / __/ ___) | _ | |_| | _
|
5
|
-
# |___/ \__,_||_| \__,_||_.__/ |_||_| |_| |_| |_____||____/ (_) \___/ (_)
|
1
|
+
# _ _ _ ____ ____ ___ __
|
2
|
+
# ___ __ _ | | __ _ | |__ (_) _ __ ___ |___ \ | ___| / _ \ / /_
|
3
|
+
# / __| / _` || | / _` || '_ \ | || '_ ` _ \ __) ||___ \ | | | | | '_ \
|
4
|
+
# \__ \| (_| || || (_| || |_) || || | | | | | / __/ ___) | _ | |_| | _ | (_) |
|
5
|
+
# |___/ \__,_||_| \__,_||_.__/ |_||_| |_| |_| |_____||____/ (_) \___/ (_) \___/
|
6
6
|
# discrete event simulation
|
7
7
|
#
|
8
8
|
# see www.salabim.org for more information, the documentation and license information
|
9
9
|
|
10
|
-
__version__ = "25.0.
|
10
|
+
__version__ = "25.0.6"
|
11
11
|
import heapq
|
12
12
|
import random
|
13
13
|
import time
|
@@ -42,7 +42,7 @@ import urllib.error
|
|
42
42
|
import base64
|
43
43
|
import zipfile
|
44
44
|
from pathlib import Path
|
45
|
-
|
45
|
+
|
46
46
|
|
47
47
|
from typing import Any, Union, Iterable, Tuple, List, Callable, TextIO, Dict, Set, Type, Hashable, Optional
|
48
48
|
|
@@ -99,7 +99,8 @@ _ANSI_to_rgb = {
|
|
99
99
|
"\033[0m": (),
|
100
100
|
}
|
101
101
|
|
102
|
-
ANSI=types.SimpleNamespace(**_color_name_to_ANSI)
|
102
|
+
ANSI = types.SimpleNamespace(**_color_name_to_ANSI)
|
103
|
+
|
103
104
|
|
104
105
|
def a_log(*args):
|
105
106
|
if not hasattr(a_log, "a_logfile_name"):
|
@@ -484,10 +485,10 @@ class Monitor:
|
|
484
485
|
fill: Iterable = None,
|
485
486
|
stats_only: bool = False,
|
486
487
|
env: "Environment" = None,
|
487
|
-
*args,
|
488
488
|
**kwargs,
|
489
489
|
):
|
490
490
|
self.env = _set_env(env)
|
491
|
+
_check_overlapping_parameters(self, "__init__", "setup")
|
491
492
|
|
492
493
|
if isinstance(self.env, Environment):
|
493
494
|
_set_name(name, self.env._nameserializeMonitor, self)
|
@@ -532,7 +533,7 @@ class Monitor:
|
|
532
533
|
self._x.extend(fill)
|
533
534
|
self._t.extend(len(fill) * [self.env._now])
|
534
535
|
|
535
|
-
self.setup(
|
536
|
+
self.setup(**kwargs)
|
536
537
|
|
537
538
|
def __eq__(self, other):
|
538
539
|
if isinstance(other, Monitor):
|
@@ -4356,8 +4357,9 @@ class Queue:
|
|
4356
4357
|
if omitted, default_env will be used
|
4357
4358
|
"""
|
4358
4359
|
|
4359
|
-
def __init__(self, name: str = None, monitor: Any = True, fill: Iterable = None, capacity: float = inf, env: "Environment" = None,
|
4360
|
+
def __init__(self, name: str = None, monitor: Any = True, fill: Iterable = None, capacity: float = inf, env: "Environment" = None, **kwargs) -> None:
|
4360
4361
|
self.env = _set_env(env)
|
4362
|
+
_check_overlapping_parameters(self, "__init__", "setup")
|
4361
4363
|
|
4362
4364
|
_set_name(name, self.env._nameserializeQueue, self)
|
4363
4365
|
self._head = Qmember()
|
@@ -4390,7 +4392,7 @@ class Queue:
|
|
4390
4392
|
c.enter(self)
|
4391
4393
|
if self.env._trace:
|
4392
4394
|
self.env.print_trace("", "", self.name() + " create")
|
4393
|
-
self.setup(
|
4395
|
+
self.setup(**kwargs)
|
4394
4396
|
|
4395
4397
|
def setup(self) -> None:
|
4396
4398
|
"""
|
@@ -5896,6 +5898,7 @@ class Animate3dBase(DynamicClass):
|
|
5896
5898
|
) -> None:
|
5897
5899
|
super().__init__()
|
5898
5900
|
self.env = _set_env(env)
|
5901
|
+
_check_overlapping_parameters(self, "__init__", "setup")
|
5899
5902
|
|
5900
5903
|
self.visible = visible
|
5901
5904
|
self.keep = keep
|
@@ -7142,6 +7145,8 @@ class Component:
|
|
7142
7145
|
):
|
7143
7146
|
self.env = _set_env(env)
|
7144
7147
|
|
7148
|
+
_check_overlapping_parameters(self, "__init__", "setup")
|
7149
|
+
|
7145
7150
|
_set_name(name, self.env._nameserializeComponent, self)
|
7146
7151
|
self._qmembers = {}
|
7147
7152
|
self._process = None
|
@@ -7196,9 +7201,13 @@ class Component:
|
|
7196
7201
|
else:
|
7197
7202
|
self.env.print_trace("", "", self.name() + " create data component", self._modetxt())
|
7198
7203
|
else:
|
7204
|
+
_check_overlapping_parameters(self, "__init__", process_name,process=p)
|
7205
|
+
_check_overlapping_parameters(self, "setup", process_name,process=p)
|
7206
|
+
|
7199
7207
|
self.env.print_trace("", "", self.name() + " create", self._modetxt())
|
7200
7208
|
|
7201
7209
|
kwargs_p = {}
|
7210
|
+
|
7202
7211
|
if kwargs:
|
7203
7212
|
parameters = inspect.signature(p).parameters
|
7204
7213
|
|
@@ -7254,6 +7263,7 @@ by adding at the end:
|
|
7254
7263
|
self.status._value = scheduled
|
7255
7264
|
if self.env._yieldless:
|
7256
7265
|
self._glet = greenlet.greenlet(lambda: self._process(**kwargs_p), parent=self.env._glet)
|
7266
|
+
self.env.glets.append(self._glet)
|
7257
7267
|
self._reschedule(scheduled_time, priority, urgent, "activate", cap_now, extra=extra)
|
7258
7268
|
self.setup(**kwargs)
|
7259
7269
|
|
@@ -7493,14 +7503,13 @@ by adding at the end:
|
|
7493
7503
|
return return_or_print(result, as_str, file)
|
7494
7504
|
|
7495
7505
|
def _push(self, t, priority, urgent, return_value=None, switch=True):
|
7496
|
-
|
7497
|
-
|
7498
|
-
|
7499
|
-
|
7500
|
-
|
7501
|
-
|
7502
|
-
|
7503
|
-
heapq.heappush(self.env._event_list, (t, priority, seq, self, return_value))
|
7506
|
+
self.env._seq += 1
|
7507
|
+
if urgent:
|
7508
|
+
seq = -self.env._seq
|
7509
|
+
else:
|
7510
|
+
seq = self.env._seq
|
7511
|
+
self._on_event_list = True
|
7512
|
+
heapq.heappush(self.env._event_list, (t, priority, seq, self, return_value))
|
7504
7513
|
if self.env._yieldless:
|
7505
7514
|
if self is self.env._current_component:
|
7506
7515
|
self.env._glet.switch()
|
@@ -7928,6 +7937,7 @@ by adding:
|
|
7928
7937
|
lineno = self.lineno_txt(add_at=True)
|
7929
7938
|
self.env.print_trace("", "", self.name() + " passivate", merge_blanks(lineno, self._modetxt()))
|
7930
7939
|
self.status._value = passive
|
7940
|
+
self._push(inf, 0, False, None)
|
7931
7941
|
|
7932
7942
|
if self.env._yieldless:
|
7933
7943
|
if self is self.env._current_component:
|
@@ -8069,6 +8079,8 @@ by adding:
|
|
8069
8079
|
self.env.print_trace("", "", "cancel " + self.name() + " " + self._modetxt())
|
8070
8080
|
self.status._value = data
|
8071
8081
|
if self.env._yieldless:
|
8082
|
+
self._glet.throw()
|
8083
|
+
self._glet = None
|
8072
8084
|
if self is self.env._current_component:
|
8073
8085
|
self.env._glet.switch()
|
8074
8086
|
|
@@ -8618,7 +8630,7 @@ by adding:
|
|
8618
8630
|
scheduled_time = fail_at + self.env._offset
|
8619
8631
|
else:
|
8620
8632
|
raise ValueError("both fail_at and fail_delay specified")
|
8621
|
-
schedule_priority=priority
|
8633
|
+
schedule_priority = priority
|
8622
8634
|
self.set_mode(mode)
|
8623
8635
|
|
8624
8636
|
self._failed = False
|
@@ -9019,7 +9031,7 @@ by adding:
|
|
9019
9031
|
raise ValueError("both fail_at and fail_delay specified")
|
9020
9032
|
|
9021
9033
|
self.set_mode(mode)
|
9022
|
-
schedule_priority=priority
|
9034
|
+
schedule_priority = priority
|
9023
9035
|
|
9024
9036
|
self._cond = cond # add test ***
|
9025
9037
|
for state in states:
|
@@ -9222,11 +9234,10 @@ by adding:
|
|
9222
9234
|
scheduled_time = fail_at + self.env._offset
|
9223
9235
|
else:
|
9224
9236
|
raise ValueError("both fail_at and fail_delay specified")
|
9225
|
-
schedule_priority=priority
|
9237
|
+
schedule_priority = priority
|
9226
9238
|
self.set_mode(mode)
|
9227
9239
|
|
9228
9240
|
for arg in args:
|
9229
|
-
|
9230
9241
|
value = True
|
9231
9242
|
priority = request_priority
|
9232
9243
|
if isinstance(arg, State):
|
@@ -9262,7 +9273,6 @@ by adding:
|
|
9262
9273
|
if not self._waits:
|
9263
9274
|
raise TypeError("no states specified")
|
9264
9275
|
|
9265
|
-
|
9266
9276
|
self._remaining_duration = scheduled_time - self.env._now
|
9267
9277
|
|
9268
9278
|
self._trywait()
|
@@ -10546,9 +10556,11 @@ class Environment:
|
|
10546
10556
|
do_reset: bool = None,
|
10547
10557
|
blind_animation: bool = False,
|
10548
10558
|
yieldless: bool = None,
|
10549
|
-
*args,
|
10550
10559
|
**kwargs,
|
10551
10560
|
):
|
10561
|
+
_check_overlapping_parameters(self, "__init__", "setup")
|
10562
|
+
|
10563
|
+
self.glets = []
|
10552
10564
|
if name is None:
|
10553
10565
|
if isdefault_env:
|
10554
10566
|
name = "default environment"
|
@@ -10713,7 +10725,7 @@ class Environment:
|
|
10713
10725
|
if ap_kwargs:
|
10714
10726
|
self.animation_parameters(**ap_kwargs)
|
10715
10727
|
|
10716
|
-
self.setup(
|
10728
|
+
self.setup(**kwargs)
|
10717
10729
|
|
10718
10730
|
# ENVIRONMENT ANNOTATION START
|
10719
10731
|
# ENVIRONMENT ANNOTATION END
|
@@ -10731,6 +10743,10 @@ class Environment:
|
|
10731
10743
|
"""
|
10732
10744
|
pass
|
10733
10745
|
|
10746
|
+
def cancel_all(self):
|
10747
|
+
for t, priority, sequence, comp, return_value in self._event_list:
|
10748
|
+
comp.cancel()
|
10749
|
+
|
10734
10750
|
def serialize(self) -> int:
|
10735
10751
|
self.serial += 1
|
10736
10752
|
return self.serial
|
@@ -11203,6 +11219,8 @@ class Environment:
|
|
11203
11219
|
if self._event_list:
|
11204
11220
|
(t, priority, seq, c, return_value) = heapq.heappop(self._event_list)
|
11205
11221
|
else:
|
11222
|
+
t = inf # only events with t==inf left, so signal that we have ended
|
11223
|
+
if t == inf:
|
11206
11224
|
c = self._main
|
11207
11225
|
if self.end_on_empty_eventlist:
|
11208
11226
|
t = self.env._now
|
@@ -23495,8 +23513,10 @@ class State:
|
|
23495
23513
|
if omitted, default_env is used
|
23496
23514
|
"""
|
23497
23515
|
|
23498
|
-
def __init__(self, name: str = None, value: Any = False, type: str = "any", monitor: bool = True, env: "Environment" = None,
|
23516
|
+
def __init__(self, name: str = None, value: Any = False, type: str = "any", monitor: bool = True, env: "Environment" = None, **kwargs):
|
23499
23517
|
self.env = _set_env(env)
|
23518
|
+
_check_overlapping_parameters(self, "__init__", "setup")
|
23519
|
+
|
23500
23520
|
_set_name(name, self.env._nameserializeState, self)
|
23501
23521
|
self._value = value
|
23502
23522
|
with self.env.suppress_trace():
|
@@ -23505,7 +23525,7 @@ class State:
|
|
23505
23525
|
self.value = _StateMonitor(parent=self, name="Value of " + self.name(), level=True, initial_tally=value, monitor=monitor, type=type, env=self.env)
|
23506
23526
|
if self.env._trace:
|
23507
23527
|
self.env.print_trace("", "", self.name() + " create", "value = " + repr(self._value))
|
23508
|
-
self.setup(
|
23528
|
+
self.setup(**kwargs)
|
23509
23529
|
|
23510
23530
|
def setup(self) -> None:
|
23511
23531
|
"""
|
@@ -23968,10 +23988,11 @@ class Resource:
|
|
23968
23988
|
honor_only_highest_priority: bool = False,
|
23969
23989
|
monitor: bool = True,
|
23970
23990
|
env: "Environment" = None,
|
23971
|
-
*args,
|
23972
23991
|
**kwargs,
|
23973
23992
|
):
|
23974
23993
|
self.env = _set_env(env)
|
23994
|
+
_check_overlapping_parameters(self, "__init__", "setup")
|
23995
|
+
|
23975
23996
|
if initial_claimed_quantity != 0:
|
23976
23997
|
if not anonymous:
|
23977
23998
|
raise ValueError("initial_claimed_quantity != 0 only allowed for anonymous resources")
|
@@ -24006,7 +24027,7 @@ class Resource:
|
|
24006
24027
|
self.occupancy = _SystemMonitor("Occupancy of " + self.name(), level=True, initial_tally=0, monitor=monitor, type="float", env=self.env)
|
24007
24028
|
if self.env._trace:
|
24008
24029
|
self.env.print_trace("", "", self.name() + " create", "capacity=" + str(self._capacity) + (" anonymous" if self._anonymous else ""))
|
24009
|
-
self.setup(
|
24030
|
+
self.setup(**kwargs)
|
24010
24031
|
|
24011
24032
|
def ispreemptive(self) -> bool:
|
24012
24033
|
"""
|
@@ -25090,6 +25111,38 @@ def _set_name(name, _nameserialize, object):
|
|
25090
25111
|
object._name = name
|
25091
25112
|
|
25092
25113
|
|
25114
|
+
def _check_overlapping_parameters(obj, method_name0, method_name1,process=None):
|
25115
|
+
"""
|
25116
|
+
this function is a helper to see whether __init__, setup and process parameters overlap
|
25117
|
+
|
25118
|
+
Parameters
|
25119
|
+
----------
|
25120
|
+
obj : object
|
25121
|
+
object to be checked (usually called with self)
|
25122
|
+
|
25123
|
+
method_name0 : str
|
25124
|
+
name of the first method to be tested
|
25125
|
+
|
25126
|
+
method_name1 : str
|
25127
|
+
name of the second method to be tested
|
25128
|
+
|
25129
|
+
process: method
|
25130
|
+
used for process check: should be the process methoc
|
25131
|
+
"""
|
25132
|
+
method0=getattr(obj, method_name0)
|
25133
|
+
|
25134
|
+
if process is None:
|
25135
|
+
method1=getattr(obj, method_name1)
|
25136
|
+
else:
|
25137
|
+
method1=process
|
25138
|
+
|
25139
|
+
overlapping_parameters = set(inspect.signature(method0).parameters) & set(inspect.signature(method1).parameters)
|
25140
|
+
if overlapping_parameters:
|
25141
|
+
raise TypeError(
|
25142
|
+
f"{obj.__class__.__name__}.{method_name1}() error: parameter '{list(overlapping_parameters)[0]}' not allowed, because it is also a parameter of {obj.__class__.__name__}.{method_name0}()"
|
25143
|
+
)
|
25144
|
+
|
25145
|
+
|
25093
25146
|
@functools.lru_cache()
|
25094
25147
|
def _screen_dimensions():
|
25095
25148
|
if PythonInExcel or AnacondaCode:
|
@@ -27821,7 +27874,12 @@ def set_environment_aliases():
|
|
27821
27874
|
return # do not set when using Sphinx build!
|
27822
27875
|
|
27823
27876
|
for name, obj in list(globals().items()):
|
27824
|
-
if (
|
27877
|
+
if (
|
27878
|
+
(not name.startswith("_") or name in ("_Trajectory", "_Distribution"))
|
27879
|
+
and name != "yieldless"
|
27880
|
+
and name != "Environment"
|
27881
|
+
and not hasattr(Environment, name)
|
27882
|
+
):
|
27825
27883
|
if inspect.isclass(obj) and obj.__module__ == Environment.__module__:
|
27826
27884
|
if issubclass(obj, Exception):
|
27827
27885
|
exec(f"Environment.{name}={name}")
|
@@ -3,8 +3,8 @@ salabim/LICENSE.txt,sha256=eTPlcDJz4G0096Qv-wfMjm1Wxbd4ilDlsYg5rN4HjWQ,1106
|
|
3
3
|
salabim/__init__.py,sha256=r7qPLvlmX0dkZDyjuTo8Jo3ex3sD1L4pmK6K5ib9vyw,56
|
4
4
|
salabim/calibri.ttf,sha256=RWpf8Uo31RfvGGNaSt9-2sXSuN87AVE_NFMRsV3LhBk,1330156
|
5
5
|
salabim/mplus-1m-regular.ttf,sha256=EuFHr90BJjuAn_r5MleJFN-WfkeWJ4tf7DweI5zr8tU,289812
|
6
|
-
salabim/salabim.py,sha256=
|
7
|
-
salabim-25.0.
|
8
|
-
salabim-25.0.
|
9
|
-
salabim-25.0.
|
10
|
-
salabim-25.0.
|
6
|
+
salabim/salabim.py,sha256=XWNVgxbGhU4tOM46WlvF2WQbsBcGwFThJIWZSdiCefA,1125722
|
7
|
+
salabim-25.0.6.dist-info/METADATA,sha256=IPb6uB8LBViARvDmZmULWzieHXyBAWkK_pNCLAkdQuY,3457
|
8
|
+
salabim-25.0.6.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
9
|
+
salabim-25.0.6.dist-info/top_level.txt,sha256=UE6zVlbi3F6T5ma1a_5TrojMaF21GYKDt9svvm0U4cQ,8
|
10
|
+
salabim-25.0.6.dist-info/RECORD,,
|
File without changes
|