robotcode-core 2.7.0__py3-none-any.whl → 2.8.0.dev8__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.
@@ -1 +1 @@
1
- __version__ = "2.7.0"
1
+ __version__ = "2.8.0-dev.8"
@@ -228,7 +228,6 @@ def _create_task_in_thread(
228
228
  _running_tasks[future] = thread
229
229
  future.add_done_callback(_remove_future_from_running_tasks)
230
230
 
231
- # TODO: don't set daemon=True because it can be deprecated in future pyhton versions
232
231
  thread.daemon = True
233
232
  return future, thread
234
233
 
robotcode/core/event.py CHANGED
@@ -31,16 +31,29 @@ class EventResultIteratorBase(Generic[_TParams, _TResult]):
31
31
 
32
32
  self._listeners: MutableSet[weakref.ref[Any]] = set()
33
33
 
34
+ # The weak reference of a listener calls this when the listener dies. It refers to the event only weakly: a
35
+ # bound method of the event would make every event with a listener a reference cycle that only the garbage
36
+ # collector frees.
37
+ self_ref = weakref.ref(self)
38
+
39
+ def remove_dead_listener(ref: Any) -> None:
40
+ event = self_ref()
41
+ if event is not None:
42
+ event.__remove_listener(ref)
43
+
44
+ self.__remove_dead_listener = remove_dead_listener
45
+
34
46
  def __remove_listener(self, ref: Any) -> None:
35
47
  with self._lock:
36
- self._listeners.remove(ref)
48
+ # a listener that `remove` took out may die only afterwards, while another thread still iterates over it
49
+ self._listeners.discard(ref)
37
50
 
38
51
  def add(self, callback: Callable[_TParams, _TResult]) -> None:
39
52
  with self._lock:
40
53
  if inspect.ismethod(callback):
41
- self._listeners.add(weakref.WeakMethod(callback, self.__remove_listener))
54
+ self._listeners.add(weakref.WeakMethod(callback, self.__remove_dead_listener))
42
55
  else:
43
- self._listeners.add(weakref.ref(callback, self.__remove_listener))
56
+ self._listeners.add(weakref.ref(callback, self.__remove_dead_listener))
44
57
 
45
58
  def remove(self, callback: Callable[_TParams, _TResult]) -> None:
46
59
  with self._lock:
@@ -376,3 +376,38 @@ def _iter_files(
376
376
  )
377
377
  elif p.is_file():
378
378
  yield p
379
+
380
+
381
+ def iter_files_includes(
382
+ path: Path,
383
+ root: Path,
384
+ ignore_files: Iterable[str] = [GIT_IGNORE_FILE],
385
+ include_hidden: bool = True,
386
+ parent_spec: Optional[IgnoreSpec] = None,
387
+ ) -> bool:
388
+ """Whether `iter_files(root, ...)` with these arguments yields the file `path`, without walking other files.
389
+
390
+ It applies the ignore files of the folders on the way from `root` to `path` as `iter_files` does.
391
+ """
392
+ path = Path(os.path.abspath(path))
393
+ root = Path(os.path.abspath(root))
394
+ if not path_is_relative_to(path, root) or not path.is_file():
395
+ return False
396
+
397
+ spec = parent_spec if parent_spec is not None else IgnoreSpec.from_list(DEFAULT_SPEC_RULES, root)
398
+ folder = root
399
+ for name in path.relative_to(root).parts:
400
+ ignore_file = next((folder / f for f in ignore_files if (folder / f).is_file()), None)
401
+ if ignore_file is not None:
402
+ spec = spec + IgnoreSpec.from_gitignore(ignore_file)
403
+ ignore_files = [ignore_file.name]
404
+
405
+ entry = folder / name
406
+ if not include_hidden and _is_hidden(entry):
407
+ return False
408
+ if spec.matches(entry):
409
+ return False
410
+
411
+ folder = entry
412
+
413
+ return True
@@ -128,6 +128,18 @@ class TextDocument:
128
128
  self._data: weakref.WeakKeyDictionary[Any, Any] = weakref.WeakKeyDictionary()
129
129
  self.opened_in_editor = False
130
130
 
131
+ # The weak reference of a cache entry calls this when the entry's function dies. It refers to the document
132
+ # only weakly: a bound method of the document would make every document with a cache entry a reference cycle
133
+ # that only the garbage collector frees.
134
+ self_ref = weakref.ref(self)
135
+
136
+ def remove_dead_cache_entry(ref: Any) -> None:
137
+ document = self_ref()
138
+ if document is not None:
139
+ document.__remove_cache_entry(ref)
140
+
141
+ self.__remove_dead_cache_entry = remove_dead_cache_entry
142
+
131
143
  @property
132
144
  def version(self) -> Optional[int]:
133
145
  return self._version
@@ -159,6 +171,11 @@ class TextDocument:
159
171
  def save(self, version: Optional[int], text: Optional[str]) -> None:
160
172
  self.apply_full_change(version, text, save=True)
161
173
 
174
+ def mark_saved(self) -> None:
175
+ """Remember the current text as the saved one, which `revert` returns to, without invalidating the caches."""
176
+ with self._lock:
177
+ self._orig_text = self._text
178
+
162
179
  def revert(self, version: Optional[int]) -> bool:
163
180
  if self._orig_text != self._text or self._orig_version != self._version:
164
181
  self.apply_full_change(version or self._orig_version, self._orig_text)
@@ -344,9 +361,9 @@ class TextDocument:
344
361
 
345
362
  def __get_cache_reference(self, entry: Callable[..., Any], /, *, add_remove: bool = True) -> "weakref.ref[Any]":
346
363
  if inspect.ismethod(entry):
347
- return weakref.WeakMethod(entry, self.__remove_cache_entry if add_remove else None)
364
+ return weakref.WeakMethod(entry, self.__remove_dead_cache_entry if add_remove else None)
348
365
 
349
- return weakref.ref(entry, self.__remove_cache_entry if add_remove else None)
366
+ return weakref.ref(entry, self.__remove_dead_cache_entry if add_remove else None)
350
367
 
351
368
  def get_cache_value(self, entry: Callable[[Self], _T]) -> Optional[_T]:
352
369
  reference = self.__get_cache_reference(entry)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: robotcode-core
3
- Version: 2.7.0
3
+ Version: 2.8.0-dev.8
4
4
  Summary: Some core classes for RobotCode
5
5
  Project-URL: Homepage, https://robotcode.io
6
6
  Project-URL: Donate, https://opencollective.com/robotcode
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
22
  Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Programming Language :: Python :: 3.15
23
24
  Classifier: Programming Language :: Python :: Implementation :: CPython
24
25
  Classifier: Programming Language :: Python :: Implementation :: PyPy
25
26
  Classifier: Topic :: Utilities
@@ -1,14 +1,14 @@
1
1
  robotcode/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- robotcode/core/__version__.py,sha256=EtKWW0Hnl5oWglRNH0HZigvcDT2FEs58ek8buJdwW1E,22
2
+ robotcode/core/__version__.py,sha256=JvoVcYcO_7K_aZkOPOeHH31iT5EQpvrGTx1sNBjoeYU,28
3
3
  robotcode/core/async_tools.py,sha256=pU12trR8-w4oUoLXiV5uGQ9weGZS25b_DXCNwbbhcfI,12843
4
- robotcode/core/concurrent.py,sha256=lcAUt0TDspb1Inxo1KTZpr-vwdEKUco_o4N41SUzb1A,7147
4
+ robotcode/core/concurrent.py,sha256=-WPaxSsS7Vgzc3PyANtfBLHznZTPZ36T0ftRHzKO584,7058
5
5
  robotcode/core/documents_manager.py,sha256=zxrncZA_zxOAFgUWdItUixfLOFnTFla7-NrOTlblTMU,7613
6
- robotcode/core/event.py,sha256=7WPZ9lRV9HvObfA3h8OtvTdCCXd8k5Fnhdrdis1l-s0,4875
6
+ robotcode/core/event.py,sha256=AytdlzTCmTa_6i11nTxb50o9MAF1czRRadDwB6N0z9w,5522
7
7
  robotcode/core/filewatcher.py,sha256=Osxwq7xJNmhF3nGNP2NHk1HynTLdVuMlt4XYrDmF7aM,2300
8
- robotcode/core/ignore_spec.py,sha256=a9N3WSQialv2vK-GDc-0MpW6sdXsYO771Jkp_pqnzH8,12127
8
+ robotcode/core/ignore_spec.py,sha256=y_sFU-Z__xkpIW8MXcAWzl0vQQtKacZINaA0NkQ7Lw8,13334
9
9
  robotcode/core/language.py,sha256=1b6vhmwiYkEXtQ2_45iqXdAG5KD1sdenGyAZzML7gNY,1047
10
10
  robotcode/core/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
11
- robotcode/core/text_document.py,sha256=vmnhyOR6d48s48f50c9924Ras7WEEMu_dOrXlK-ncPE,12920
11
+ robotcode/core/text_document.py,sha256=NqQQ4YHHHWkgqMBnLxxC5fQvxLeQ9hhEJkaEm7Wai_c,13712
12
12
  robotcode/core/types.py,sha256=xxDJsW3h_ygJTRtehalYAU9LsMHdbbBHCQapWA27i38,443
13
13
  robotcode/core/uri.py,sha256=BufKNvq2JrzgUQ3T_R4fdTUBJI_7tFGIbvxZCGtyyqQ,5953
14
14
  robotcode/core/workspace.py,sha256=QV2qffKfgvZg_pqiTSrmqLA22I6evEfJpAVi8YeAvC8,2631
@@ -27,6 +27,6 @@ robotcode/core/utils/path.py,sha256=RDhRcLFXami154-zCe6GeYFyuL2Fuwrd8Teh-bPlIbA,
27
27
  robotcode/core/utils/process.py,sha256=nwTTmAyjcDybcO_fq0ZbZK_76ndBFO324z9cxni8TuU,679
28
28
  robotcode/core/utils/safe_eval.py,sha256=ES12mwdqNH4iHsP23sEBW6_bgGjS5DKFfgSfxP97-ok,1448
29
29
  robotcode/core/utils/version.py,sha256=uXcvqOFLbaSH5EWL6OwRDZjGteFzwaqt0Ll2Rf5h008,1373
30
- robotcode_core-2.7.0.dist-info/METADATA,sha256=ozJa2ZK7aOzCvdrApoFwyLWhHRkfAEgwThT7FjGPIaQ,2705
31
- robotcode_core-2.7.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
32
- robotcode_core-2.7.0.dist-info/RECORD,,
30
+ robotcode_core-2.8.0.dev8.dist-info/METADATA,sha256=9Ag4lOPETgknae3zmutFtI0LvkBks9KHvzdJjGCG7LA,2762
31
+ robotcode_core-2.8.0.dev8.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
32
+ robotcode_core-2.8.0.dev8.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.31.0
2
+ Generator: hatchling 1.32.4
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any