salabim 25.0.9.post3__py3-none-any.whl → 25.0.9.post4__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 CHANGED
@@ -46,22 +46,15 @@ from pathlib import Path
46
46
 
47
47
  from typing import Any, Union, Iterable, Tuple, List, Callable, TextIO, Dict, Set, Type, Hashable, Optional
48
48
 
49
- # module = salabim # for PythonInExcel runner
50
-
51
49
  dataframe = None # to please PyLance
52
50
 
53
51
  ColorType = Union[str, Iterable[float]]
54
52
 
55
53
  Pythonista = sys.platform == "ios"
56
54
  Windows = sys.platform.startswith("win")
57
- PyDroid = sys.platform == "linux" and any("pydroid" in v for v in os.environ.values())
58
55
  PyPy = platform.python_implementation() == "PyPy"
59
56
  Chromebook = "penguin" in platform.uname()
60
- #Xlwings="xlwings" in sys.modules
61
- Xlwings=sys.platform=="emscripten"
62
- Xlwings1="xlwings" in sys.modules
63
-
64
- Embedded = False # (not ("__file__" in globals())) or ((sys.platform == "emscripten") and not Xlwings) # Python In Excel or pyoide (AnacondaCode or xlwings lite)
57
+ Xlwings = "xlwings" in sys.modules
65
58
 
66
59
  _color_name_to_ANSI = dict(
67
60
  dark_black="\033[0;30m",
@@ -117,71 +110,6 @@ def a_log(*args):
117
110
 
118
111
  class g: ...
119
112
 
120
-
121
- if Embedded:
122
- _pie_result = []
123
-
124
- def pie_result():
125
- return _pie_result
126
-
127
- class b64_file_handler(io.IOBase):
128
- """
129
- special purpose file handler for Python in Excel
130
-
131
- Parameters
132
- ----------
133
- name : str
134
- name of file
135
-
136
- result : list
137
- b64 information will be added as string(s)
138
-
139
- blocksize : int
140
- b64 blocksize (default: 30000)
141
-
142
- mode : str
143
- if 't' (default): open for test
144
- if 'b': open for binary
145
-
146
- Note
147
- ----
148
- can be used as a file or in a context manager
149
- """
150
-
151
- def __init__(self, name, result, blocksize=30000, mode="t"):
152
- self._name = name
153
- self._result = result
154
- self._blocksize = blocksize
155
- if mode not in ("t", "b"):
156
- raise ValueError(f"wrong mode ({mode})")
157
- self._mode = mode
158
- self._buffer = []
159
-
160
- def __enter__(self):
161
- return self
162
-
163
- def __exit__(self, *args):
164
- self.close()
165
-
166
- def write(self, s):
167
- self._buffer.append(s)
168
-
169
- def close(self):
170
- if self._mode == "b":
171
- b = b"".join(self._buffer)
172
- else:
173
- b = "".join(self._buffer).encode("utf-8")
174
- n = self._blocksize
175
- b64 = base64.b64encode(b).decode("utf-8")
176
- self._result.append(f"<file name={self._name}>")
177
- while b64:
178
- b64_n = b64[:n]
179
- self._result.append(b64_n)
180
- b64 = b64[n:]
181
- self._result.append("</file>")
182
- super().close()
183
-
184
-
185
113
  if Pythonista:
186
114
  try:
187
115
  import scene # type: ignore
@@ -193,7 +121,7 @@ if Pythonista:
193
121
  inf = float("inf")
194
122
  nan = float("nan")
195
123
 
196
- if Pythonista or Embedded or Xlwings:
124
+ if Pythonista or Xlwings:
197
125
  _yieldless = False
198
126
  else:
199
127
  _yieldless = True
@@ -233,11 +161,9 @@ def yieldless(value: bool = None) -> bool:
233
161
  if value is not None:
234
162
  if value:
235
163
  if Pythonista:
236
- raise ValueError('yiedless mode is not allowed under Pythonista')
237
- if Embedded:
238
- raise ValueError('yiedless mode is not allowed under Python in Excel or Anaconda Code')
164
+ raise ValueError("yiedless mode is not allowed under Pythonista")
239
165
  if Xlwings:
240
- raise ValueError('yiedless mode is not allowed under xlwings lite')
166
+ raise ValueError("yiedless mode is not allowed under xlwings lite")
241
167
  _yieldless = value
242
168
  return _yieldless
243
169
 
@@ -7211,8 +7137,8 @@ class Component:
7211
7137
  else:
7212
7138
  self.env.print_trace("", "", self.name() + " create data component", self._modetxt())
7213
7139
  else:
7214
- _check_overlapping_parameters(self, "__init__", process_name,process=p)
7215
- _check_overlapping_parameters(self, "setup", process_name,process=p)
7140
+ _check_overlapping_parameters(self, "__init__", process_name, process=p)
7141
+ _check_overlapping_parameters(self, "setup", process_name, process=p)
7216
7142
 
7217
7143
  self.env.print_trace("", "", self.name() + " create", self._modetxt())
7218
7144
 
@@ -7512,7 +7438,7 @@ by adding at the end:
7512
7438
  return return_or_print(result, as_str, file)
7513
7439
 
7514
7440
  def _push(self, t, priority, urgent, return_value=None, switch=True):
7515
- if t!=inf:
7441
+ if t != inf:
7516
7442
  self.env._seq += 1
7517
7443
  if urgent:
7518
7444
  seq = -self.env._seq
@@ -10658,22 +10584,19 @@ class Environment:
10658
10584
  self.stopped = False
10659
10585
  self._paused = False
10660
10586
  self.last_s0 = ""
10661
- if Embedded or Xlwings:
10587
+ if Xlwings:
10662
10588
  if blind_animation is None:
10663
- blind_animation=True
10589
+ blind_animation = True
10664
10590
  if not blind_animation:
10665
10591
  raise ValueError("blind_animation may not be False under xlwings lite")
10666
10592
  else:
10667
10593
  if blind_animation is None:
10668
- blind_animation=False
10594
+ blind_animation = False
10669
10595
  self._blind_animation = blind_animation
10670
10596
 
10671
10597
  if self._blind_animation:
10672
10598
  with self.suppress_trace():
10673
10599
  self._blind_video_maker = _BlindVideoMaker(process="", suppress_trace=True)
10674
- if PyDroid:
10675
- if g.tkinter_loaded == "?":
10676
- g.tkinter_loaded = "tkinter" in sys.modules
10677
10600
 
10678
10601
  if Pythonista:
10679
10602
  self._width, self._height = ui.get_screen_size()
@@ -11532,8 +11455,6 @@ class Environment:
11532
11455
 
11533
11456
  If no codec is given, MJPG will be used for .avi files, otherwise .mp4v
11534
11457
 
11535
- Under PyDroid only .avi files are supported.
11536
-
11537
11458
  video_repeat : int
11538
11459
  number of times animated gif or png should be repeated
11539
11460
 
@@ -11855,8 +11776,6 @@ class Environment:
11855
11776
  self._video_name = self._video_name[:-5] # get rid of codec
11856
11777
  else:
11857
11778
  codec = "MJPG" if extension.lower() == ".avi" else "mp4v"
11858
- if PyDroid and extension.lower() != ".avi":
11859
- raise ValueError("PyDroid can only produce .avi videos, not " + extension)
11860
11779
  can_video(try_only=False)
11861
11780
  fourcc = cv2.VideoWriter_fourcc(*codec)
11862
11781
  if video_path.is_file():
@@ -11960,59 +11879,34 @@ class Environment:
11960
11879
  if self._video_pingpong:
11961
11880
  self._images.extend(self._images[::-1])
11962
11881
  if self._video_repeat == 1: # in case of repeat == 1, loop should not be specified (otherwise, it might show twice)
11963
- if Embedded:
11964
- with b64_file_handler(self._video_name, mode="b", result=_pie_result) as f:
11882
+ for _ in range(2): # normally runs only once
11883
+ try:
11965
11884
  self._images[0].save(
11966
- f,
11885
+ self._video_name,
11967
11886
  disposal=2,
11968
11887
  save_all=True,
11969
11888
  append_images=self._images[1:],
11970
11889
  duration=round(1000 / self._real_fps),
11971
11890
  optimize=False,
11972
- format="GIF",
11973
11891
  )
11974
- else:
11975
- for _ in range(2): # normally runs only once
11976
- try:
11977
- self._images[0].save(
11978
- self._video_name,
11979
- disposal=2,
11980
- save_all=True,
11981
- append_images=self._images[1:],
11982
- duration=round(1000 / self._real_fps),
11983
- optimize=False,
11984
- )
11985
- break
11986
- except ValueError: # prevent bug in Python 3.13
11987
- self._images = [image.convert("RGB") for image in self._images]
11892
+ break
11893
+ except ValueError: # prevent bug in Python 3.13
11894
+ self._images = [image.convert("RGB") for image in self._images]
11988
11895
 
11989
11896
  else:
11990
- if Embedded:
11991
- with b64_file_handler(self._video_name, mode="b", result=_pie_result) as f:
11897
+ for _ in range(2): # normally runs only once
11898
+ try:
11992
11899
  self._images[0].save(
11993
- f,
11900
+ self._video_name,
11994
11901
  disposal=2,
11995
11902
  save_all=True,
11996
11903
  append_images=self._images[1:],
11997
11904
  loop=self._video_repeat,
11998
11905
  duration=round(1000 / self._real_fps),
11999
11906
  optimize=False,
12000
- format="GIF",
12001
11907
  )
12002
- else:
12003
- for _ in range(2): # normally runs only once
12004
- try:
12005
- self._images[0].save(
12006
- self._video_name,
12007
- disposal=2,
12008
- save_all=True,
12009
- append_images=self._images[1:],
12010
- loop=self._video_repeat,
12011
- duration=round(1000 / self._real_fps),
12012
- optimize=False,
12013
- )
12014
- except ValueError: # prevent bug in Python 3.13
12015
- self._images = [image.convert("RGB") for image in self._images]
11908
+ except ValueError: # prevent bug in Python 3.13
11909
+ self._images = [image.convert("RGB") for image in self._images]
12016
11910
 
12017
11911
  del self._images
12018
11912
  elif self._video_out == "png":
@@ -13604,13 +13498,8 @@ class Environment:
13604
13498
  mode = "RGB"
13605
13499
  else:
13606
13500
  raise ValueError("extension " + extension + " not supported")
13607
- if Embedded:
13608
- with b64_file_handler(str(filename), mode="b", result=_pie_result) as f:
13609
- format = "jpeg" if extension == ".jpg" else extension[1:]
13610
- self._capture_image(mode, video_mode).save(f, format=format)
13611
- else:
13612
- filename_path.parent.mkdir(parents=True, exist_ok=True)
13613
- self._capture_image(mode, video_mode).save(str(filename))
13501
+ filename_path.parent.mkdir(parents=True, exist_ok=True)
13502
+ self._capture_image(mode, video_mode).save(str(filename))
13614
13503
 
13615
13504
  def modelname_width(self):
13616
13505
  if Environment.cached_modelname_width[0] != self._modelname:
@@ -14621,16 +14510,14 @@ class Environment:
14621
14510
  note that the header is only printed if trace=True
14622
14511
  """
14623
14512
  len_s1 = len(self.time_to_str(0))
14624
- self.print_trace((len_s1 - 4) * " " + "time", "current component", "action", "information", "" if (Embedded) else "line#")
14625
- self.print_trace(len_s1 * "-", 20 * "-", 35 * "-", 48 * "-", "" if (Embedded) else 6 * "-")
14513
+ self.print_trace((len_s1 - 4) * " " + "time", "current component", "action", "information", "line#")
14514
+ self.print_trace(len_s1 * "-", 20 * "-", 35 * "-", 48 * "-", 6 * "-")
14626
14515
  for ref in range(len(self._source_files)):
14627
14516
  for fullfilename, iref in self._source_files.items():
14628
14517
  if ref == iref:
14629
14518
  self._print_legend(iref)
14630
14519
 
14631
14520
  def _print_legend(self, ref):
14632
- if Embedded:
14633
- return
14634
14521
  if ref:
14635
14522
  s = "line numbers prefixed by " + chr(ord("A") + ref - 1) + " refer to"
14636
14523
  else:
@@ -14647,8 +14534,6 @@ class Environment:
14647
14534
  return self.filename_lineno_to_str(frameinfo.filename, frameinfo.lineno)
14648
14535
 
14649
14536
  def filename_lineno_to_str(self, filename, lineno):
14650
- if Embedded:
14651
- return "n/a"
14652
14537
  if Path(filename).name == Path(__file__).name: # internal salabim address
14653
14538
  return "n/a"
14654
14539
  ref = self._source_files.get(filename)
@@ -25118,7 +25003,7 @@ def _set_name(name, _nameserialize, object):
25118
25003
  object._name = name
25119
25004
 
25120
25005
 
25121
- def _check_overlapping_parameters(obj, method_name0, method_name1,process=None):
25006
+ def _check_overlapping_parameters(obj, method_name0, method_name1, process=None):
25122
25007
  """
25123
25008
  this function is a helper to see whether __init__, setup and process parameters overlap
25124
25009
 
@@ -25136,12 +25021,12 @@ def _check_overlapping_parameters(obj, method_name0, method_name1,process=None):
25136
25021
  process: method
25137
25022
  used for process check: should be the process methoc
25138
25023
  """
25139
- method0=getattr(obj, method_name0)
25024
+ method0 = getattr(obj, method_name0)
25140
25025
 
25141
25026
  if process is None:
25142
- method1=getattr(obj, method_name1)
25027
+ method1 = getattr(obj, method_name1)
25143
25028
  else:
25144
- method1=process
25029
+ method1 = process
25145
25030
 
25146
25031
  overlapping_parameters = set(inspect.signature(method0).parameters) & set(inspect.signature(method1).parameters)
25147
25032
  if overlapping_parameters:
@@ -25152,7 +25037,7 @@ def _check_overlapping_parameters(obj, method_name0, method_name1,process=None):
25152
25037
 
25153
25038
  @functools.lru_cache()
25154
25039
  def _screen_dimensions():
25155
- if Embedded or Xlwings:
25040
+ if Xlwings:
25156
25041
  return 1024, 768
25157
25042
  if Pythonista:
25158
25043
  screen_width, screen_height = ui.get_screen_size()
@@ -27180,7 +27065,7 @@ def _std_fonts():
27180
27065
 
27181
27066
 
27182
27067
  def fonts():
27183
- if Embedded or Xlwings:
27068
+ if Xlwings:
27184
27069
  return []
27185
27070
  if not hasattr(fonts, "font_list"):
27186
27071
  fonts.font_list = []
@@ -27453,7 +27338,7 @@ def can_animate(try_only: bool = True) -> bool:
27453
27338
  except ImportError:
27454
27339
  ImageGrab = None
27455
27340
 
27456
- if not Pythonista and not (Embedded or Xlwings):
27341
+ if not Pythonista and not Xlwings:
27457
27342
  from PIL import ImageTk
27458
27343
  except ImportError:
27459
27344
  if try_only:
@@ -27462,12 +27347,7 @@ def can_animate(try_only: bool = True) -> bool:
27462
27347
 
27463
27348
  g.dummy_image = Image.new("RGBA", (1, 1), (0, 0, 0, 0))
27464
27349
 
27465
- if not Pythonista and not (Embedded or Xlwings):
27466
- if PyDroid:
27467
- if not g.tkinter_loaded:
27468
- if try_only:
27469
- return False
27470
- raise ImportError("PyDroid animation requires that the main program imports tkinter")
27350
+ if not Pythonista and not Xlwings:
27471
27351
  try:
27472
27352
  import tkinter
27473
27353
  import tkinter.font
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: salabim
3
- Version: 25.0.9.post3
3
+ Version: 25.0.9.post4
4
4
  Summary: salabim - discrete event simulation in Python
5
5
  Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
6
  Project-URL: Homepage, https://salabim.org
@@ -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=_uh3TROL6eI6TrOSM9QrPdMwg-i7qSFRcbqBlAaBanE,1126024
7
- salabim-25.0.9.post3.dist-info/METADATA,sha256=NJ9TPT8vmUIHwE-9uBTKKeW3Wh4eAVMf3Yfg3oNwfG8,3405
8
- salabim-25.0.9.post3.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
9
- salabim-25.0.9.post3.dist-info/top_level.txt,sha256=UE6zVlbi3F6T5ma1a_5TrojMaF21GYKDt9svvm0U4cQ,8
10
- salabim-25.0.9.post3.dist-info/RECORD,,
6
+ salabim/salabim.py,sha256=hL-5b2WhppIVwwldm-O5-pCFOEHRoFt1DhoIhCHf9-w,1121320
7
+ salabim-25.0.9.post4.dist-info/METADATA,sha256=t2mmahEmxd0puFxYki_G4vcb1k05dVyw9F-IQuNjs2A,3405
8
+ salabim-25.0.9.post4.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
9
+ salabim-25.0.9.post4.dist-info/top_level.txt,sha256=UE6zVlbi3F6T5ma1a_5TrojMaF21GYKDt9svvm0U4cQ,8
10
+ salabim-25.0.9.post4.dist-info/RECORD,,