venv added, updated
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
from .booleandisposable import BooleanDisposable
|
||||
from .compositedisposable import CompositeDisposable
|
||||
from .disposable import Disposable
|
||||
from .multipleassignmentdisposable import MultipleAssignmentDisposable
|
||||
from .refcountdisposable import RefCountDisposable
|
||||
from .scheduleddisposable import ScheduledDisposable
|
||||
from .serialdisposable import SerialDisposable
|
||||
from .singleassignmentdisposable import SingleAssignmentDisposable
|
||||
|
||||
__all__ = [
|
||||
"BooleanDisposable",
|
||||
"CompositeDisposable",
|
||||
"Disposable",
|
||||
"MultipleAssignmentDisposable",
|
||||
"RefCountDisposable",
|
||||
"ScheduledDisposable",
|
||||
"SerialDisposable",
|
||||
"SingleAssignmentDisposable",
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
from threading import RLock
|
||||
|
||||
from reactivex.abc import DisposableBase
|
||||
|
||||
|
||||
class BooleanDisposable(DisposableBase):
|
||||
"""Represents a Disposable that can be checked for status."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initializes a new instance of the BooleanDisposable class."""
|
||||
|
||||
self.is_disposed = False
|
||||
self.lock = RLock()
|
||||
|
||||
super().__init__()
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Sets the status to disposed"""
|
||||
|
||||
self.is_disposed = True
|
||||
@@ -0,0 +1,103 @@
|
||||
from threading import RLock
|
||||
from typing import Any, List
|
||||
|
||||
from reactivex import abc
|
||||
|
||||
|
||||
class CompositeDisposable(abc.DisposableBase):
|
||||
"""Represents a group of disposable resources that are disposed
|
||||
together"""
|
||||
|
||||
def __init__(self, *args: Any):
|
||||
if args and isinstance(args[0], list):
|
||||
self.disposable: List[abc.DisposableBase] = args[0]
|
||||
else:
|
||||
self.disposable = list(args)
|
||||
|
||||
self.is_disposed = False
|
||||
self.lock = RLock()
|
||||
super(CompositeDisposable, self).__init__()
|
||||
|
||||
def add(self, item: abc.DisposableBase) -> None:
|
||||
"""Adds a disposable to the CompositeDisposable or disposes the
|
||||
disposable if the CompositeDisposable is disposed
|
||||
|
||||
Args:
|
||||
item: Disposable to add."""
|
||||
|
||||
should_dispose = False
|
||||
with self.lock:
|
||||
if self.is_disposed:
|
||||
should_dispose = True
|
||||
else:
|
||||
self.disposable.append(item)
|
||||
|
||||
if should_dispose:
|
||||
item.dispose()
|
||||
|
||||
def remove(self, item: abc.DisposableBase) -> bool:
|
||||
"""Removes and disposes the first occurrence of a disposable
|
||||
from the CompositeDisposable."""
|
||||
|
||||
if self.is_disposed:
|
||||
return False
|
||||
|
||||
should_dispose = False
|
||||
with self.lock:
|
||||
if item in self.disposable:
|
||||
self.disposable.remove(item)
|
||||
should_dispose = True
|
||||
|
||||
if should_dispose:
|
||||
item.dispose()
|
||||
|
||||
return should_dispose
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Disposes all disposable in the group and removes them from
|
||||
the group."""
|
||||
|
||||
if self.is_disposed:
|
||||
return
|
||||
|
||||
with self.lock:
|
||||
self.is_disposed = True
|
||||
current_disposable = self.disposable
|
||||
self.disposable = []
|
||||
|
||||
for disp in current_disposable:
|
||||
disp.dispose()
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Removes and disposes all disposable from the
|
||||
CompositeDisposable, but does not dispose the
|
||||
CompositeDisposable."""
|
||||
|
||||
with self.lock:
|
||||
current_disposable = self.disposable
|
||||
self.disposable = []
|
||||
|
||||
for disposable in current_disposable:
|
||||
disposable.dispose()
|
||||
|
||||
def contains(self, item: abc.DisposableBase) -> bool:
|
||||
"""Determines whether the CompositeDisposable contains a specific
|
||||
disposable.
|
||||
|
||||
Args:
|
||||
item: Disposable to search for
|
||||
|
||||
Returns:
|
||||
True if the disposable was found; otherwise, False"""
|
||||
|
||||
return item in self.disposable
|
||||
|
||||
def to_list(self) -> List[abc.DisposableBase]:
|
||||
return self.disposable[:]
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(self.disposable)
|
||||
|
||||
@property
|
||||
def length(self) -> int:
|
||||
return len(self.disposable)
|
||||
@@ -0,0 +1,43 @@
|
||||
from threading import RLock
|
||||
from typing import Optional
|
||||
|
||||
from reactivex import typing
|
||||
from reactivex.abc import DisposableBase
|
||||
from reactivex.internal import noop
|
||||
from reactivex.typing import Action
|
||||
|
||||
|
||||
class Disposable(DisposableBase):
|
||||
"""Main disposable class"""
|
||||
|
||||
def __init__(self, action: Optional[typing.Action] = None) -> None:
|
||||
"""Creates a disposable object that invokes the specified
|
||||
action when disposed.
|
||||
|
||||
Args:
|
||||
action: Action to run during the first call to dispose.
|
||||
The action is guaranteed to be run at most once.
|
||||
|
||||
Returns:
|
||||
The disposable object that runs the given action upon
|
||||
disposal.
|
||||
"""
|
||||
|
||||
self.is_disposed = False
|
||||
self.action: Action = action or noop
|
||||
|
||||
self.lock = RLock()
|
||||
|
||||
super().__init__()
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Performs the task of cleaning up resources."""
|
||||
|
||||
dispose = False
|
||||
with self.lock:
|
||||
if not self.is_disposed:
|
||||
dispose = True
|
||||
self.is_disposed = True
|
||||
|
||||
if dispose:
|
||||
self.action()
|
||||
@@ -0,0 +1,49 @@
|
||||
from threading import RLock
|
||||
from typing import Optional
|
||||
|
||||
from reactivex.abc import DisposableBase
|
||||
|
||||
|
||||
class MultipleAssignmentDisposable(DisposableBase):
|
||||
"""Represents a disposable resource whose underlying disposable
|
||||
resource can be replaced by another disposable resource."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.current: Optional[DisposableBase] = None
|
||||
self.is_disposed = False
|
||||
self.lock = RLock()
|
||||
|
||||
super().__init__()
|
||||
|
||||
def get_disposable(self) -> Optional[DisposableBase]:
|
||||
return self.current
|
||||
|
||||
def set_disposable(self, value: DisposableBase) -> None:
|
||||
"""If the MultipleAssignmentDisposable has already been
|
||||
disposed, assignment to this property causes immediate disposal
|
||||
of the given disposable object."""
|
||||
|
||||
with self.lock:
|
||||
should_dispose = self.is_disposed
|
||||
if not should_dispose:
|
||||
self.current = value
|
||||
|
||||
if should_dispose and value is not None:
|
||||
value.dispose()
|
||||
|
||||
disposable = property(get_disposable, set_disposable)
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Disposes the underlying disposable as well as all future
|
||||
replacements."""
|
||||
|
||||
old = None
|
||||
|
||||
with self.lock:
|
||||
if not self.is_disposed:
|
||||
self.is_disposed = True
|
||||
old = self.current
|
||||
self.current = None
|
||||
|
||||
if old is not None:
|
||||
old.dispose()
|
||||
@@ -0,0 +1,82 @@
|
||||
from threading import RLock
|
||||
from typing import Optional
|
||||
|
||||
from reactivex.abc import DisposableBase
|
||||
|
||||
from .disposable import Disposable
|
||||
|
||||
|
||||
class RefCountDisposable(DisposableBase):
|
||||
"""Represents a disposable resource that only disposes its underlying
|
||||
disposable resource when all dependent disposable objects have been
|
||||
disposed."""
|
||||
|
||||
class InnerDisposable(DisposableBase):
|
||||
def __init__(self, parent: "RefCountDisposable") -> None:
|
||||
self.parent: Optional[RefCountDisposable] = parent
|
||||
self.is_disposed = False
|
||||
self.lock = RLock()
|
||||
|
||||
def dispose(self) -> None:
|
||||
with self.lock:
|
||||
parent = self.parent
|
||||
self.parent = None
|
||||
|
||||
if parent is not None:
|
||||
parent.release()
|
||||
|
||||
def __init__(self, disposable: DisposableBase) -> None:
|
||||
"""Initializes a new instance of the RefCountDisposable class with the
|
||||
specified disposable."""
|
||||
|
||||
self.underlying_disposable = disposable
|
||||
self.is_primary_disposed = False
|
||||
self.is_disposed = False
|
||||
self.lock = RLock()
|
||||
self.count = 0
|
||||
|
||||
super().__init__()
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Disposes the underlying disposable only when all dependent
|
||||
disposable have been disposed."""
|
||||
|
||||
if self.is_disposed:
|
||||
return
|
||||
|
||||
underlying_disposable = None
|
||||
with self.lock:
|
||||
if not self.is_primary_disposed:
|
||||
self.is_primary_disposed = True
|
||||
if not self.count:
|
||||
self.is_disposed = True
|
||||
underlying_disposable = self.underlying_disposable
|
||||
|
||||
if underlying_disposable is not None:
|
||||
underlying_disposable.dispose()
|
||||
|
||||
def release(self) -> None:
|
||||
if self.is_disposed:
|
||||
return
|
||||
|
||||
should_dispose = False
|
||||
with self.lock:
|
||||
self.count -= 1
|
||||
if not self.count and self.is_primary_disposed:
|
||||
self.is_disposed = True
|
||||
should_dispose = True
|
||||
|
||||
if should_dispose:
|
||||
self.underlying_disposable.dispose()
|
||||
|
||||
@property
|
||||
def disposable(self) -> DisposableBase:
|
||||
"""Returns a dependent disposable that when disposed decreases the
|
||||
refcount on the underlying disposable."""
|
||||
|
||||
with self.lock:
|
||||
if self.is_disposed:
|
||||
return Disposable()
|
||||
|
||||
self.count += 1
|
||||
return self.InnerDisposable(self)
|
||||
@@ -0,0 +1,38 @@
|
||||
from threading import RLock
|
||||
from typing import Any
|
||||
|
||||
from reactivex import abc
|
||||
|
||||
from .singleassignmentdisposable import SingleAssignmentDisposable
|
||||
|
||||
|
||||
class ScheduledDisposable(abc.DisposableBase):
|
||||
"""Represents a disposable resource whose disposal invocation will
|
||||
be scheduled on the specified Scheduler"""
|
||||
|
||||
def __init__(
|
||||
self, scheduler: abc.SchedulerBase, disposable: abc.DisposableBase
|
||||
) -> None:
|
||||
"""Initializes a new instance of the ScheduledDisposable class
|
||||
that uses a Scheduler on which to dispose the disposable."""
|
||||
|
||||
self.scheduler = scheduler
|
||||
self.disposable = SingleAssignmentDisposable()
|
||||
self.disposable.disposable = disposable
|
||||
self.lock = RLock()
|
||||
|
||||
super().__init__()
|
||||
|
||||
@property
|
||||
def is_disposed(self) -> bool:
|
||||
return self.disposable.is_disposed
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Disposes the wrapped disposable on the provided scheduler."""
|
||||
|
||||
def action(scheduler: abc.SchedulerBase, state: Any) -> None:
|
||||
"""Scheduled dispose action"""
|
||||
|
||||
self.disposable.dispose()
|
||||
|
||||
self.scheduler.schedule(action)
|
||||
@@ -0,0 +1,58 @@
|
||||
from threading import RLock
|
||||
from typing import Optional
|
||||
|
||||
from reactivex import abc
|
||||
|
||||
|
||||
class SerialDisposable(abc.DisposableBase):
|
||||
"""Represents a disposable resource whose underlying disposable
|
||||
resource can be replaced by another disposable resource, causing
|
||||
automatic disposal of the previous underlying disposable resource.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.current: Optional[abc.DisposableBase] = None
|
||||
self.is_disposed = False
|
||||
self.lock = RLock()
|
||||
|
||||
super().__init__()
|
||||
|
||||
def get_disposable(self) -> Optional[abc.DisposableBase]:
|
||||
return self.current
|
||||
|
||||
def set_disposable(self, value: abc.DisposableBase) -> None:
|
||||
"""If the SerialDisposable has already been disposed, assignment
|
||||
to this property causes immediate disposal of the given
|
||||
disposable object. Assigning this property disposes the previous
|
||||
disposable object."""
|
||||
|
||||
old: Optional[abc.DisposableBase] = None
|
||||
|
||||
with self.lock:
|
||||
should_dispose = self.is_disposed
|
||||
if not should_dispose:
|
||||
old = self.current
|
||||
self.current = value
|
||||
|
||||
if old is not None:
|
||||
old.dispose()
|
||||
|
||||
if should_dispose and value is not None:
|
||||
value.dispose()
|
||||
|
||||
disposable = property(get_disposable, set_disposable)
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Disposes the underlying disposable as well as all future
|
||||
replacements."""
|
||||
|
||||
old: Optional[abc.DisposableBase] = None
|
||||
|
||||
with self.lock:
|
||||
if not self.is_disposed:
|
||||
self.is_disposed = True
|
||||
old = self.current
|
||||
self.current = None
|
||||
|
||||
if old is not None:
|
||||
old.dispose()
|
||||
@@ -0,0 +1,53 @@
|
||||
from threading import RLock
|
||||
from typing import Optional
|
||||
|
||||
from reactivex.abc import DisposableBase
|
||||
|
||||
|
||||
class SingleAssignmentDisposable(DisposableBase):
|
||||
"""Single assignment disposable.
|
||||
|
||||
Represents a disposable resource which only allows a single
|
||||
assignment of its underlying disposable resource. If an underlying
|
||||
disposable resource has already been set, future attempts to set the
|
||||
underlying disposable resource will throw an Error."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initializes a new instance of the SingleAssignmentDisposable
|
||||
class.
|
||||
"""
|
||||
self.is_disposed: bool = False
|
||||
self.current: Optional[DisposableBase] = None
|
||||
self.lock = RLock()
|
||||
|
||||
super().__init__()
|
||||
|
||||
def get_disposable(self) -> Optional[DisposableBase]:
|
||||
return self.current
|
||||
|
||||
def set_disposable(self, value: DisposableBase) -> None:
|
||||
if self.current:
|
||||
raise Exception("Disposable has already been assigned")
|
||||
|
||||
with self.lock:
|
||||
should_dispose = self.is_disposed
|
||||
if not should_dispose:
|
||||
self.current = value
|
||||
|
||||
if self.is_disposed and value:
|
||||
value.dispose()
|
||||
|
||||
disposable = property(get_disposable, set_disposable)
|
||||
|
||||
def dispose(self) -> None:
|
||||
"""Sets the status to disposed"""
|
||||
old: Optional[DisposableBase] = None
|
||||
|
||||
with self.lock:
|
||||
if not self.is_disposed:
|
||||
self.is_disposed = True
|
||||
old = self.current
|
||||
self.current = None
|
||||
|
||||
if old is not None:
|
||||
old.dispose()
|
||||
Reference in New Issue
Block a user