From 3e782aea70fe2f6ccbe7a23b20b02ce21c555a59 Mon Sep 17 00:00:00 2001
From: Anton Tetov <anton@tetov.se>
Date: Wed, 13 Oct 2021 08:59:29 +0200
Subject: [PATCH] tooling

---
 abb_egm_client/atomic_counter.py | 60 ++++++++++++++++++++++++++++++++
 environment.yml                  |  3 +-
 pyproject.toml                   |  3 ++
 setup.cfg                        | 12 ++++++-
 4 files changed, 76 insertions(+), 2 deletions(-)
 create mode 100644 abb_egm_client/atomic_counter.py

diff --git a/abb_egm_client/atomic_counter.py b/abb_egm_client/atomic_counter.py
new file mode 100644
index 0000000..a78a1da
--- /dev/null
+++ b/abb_egm_client/atomic_counter.py
@@ -0,0 +1,60 @@
+import threading
+
+
+class AtomicCounter:
+    """An atomic, thread-safe counter.
+
+    From:
+    https://gist.github.com/benhoyt/8c8a8d62debe8e5aa5340373f9c509c7#gistcomment-3142969
+
+    >>> counter = AtomicCounter()
+    >>> counter.inc()
+    1
+    >>> counter.inc(num=4)
+    5
+    >>> counter = AtomicCounter(42.5)
+    >>> counter.value
+    42.5
+    >>> counter.inc(num=0.5)
+    43.0
+    >>> counter = AtomicCounter()
+    >>> def incrementor():
+    ...     for i in range(100000):
+    ...         counter.inc()
+    >>> threads = []
+    >>> for i in range(4):
+    ...     thread = threading.Thread(target=incrementor)
+    ...     thread.start()
+    ...     threads.append(thread)
+    >>> for thread in threads:
+    ...     thread.join()
+    >>> counter.value
+    400000
+    """
+
+    def __init__(self, initial=0):
+        """Initialize a new atomic counter to given initial value"""
+        self._value = initial
+        self._lock = threading.Lock()
+
+    def inc(self, num=1):
+        """Atomically increment the counter by num and return the new value"""
+        with self._lock:
+            self._value += num
+            return self._value
+
+    def dec(self, num=1):
+        """Atomically decrement the counter by num and return the new value"""
+        with self._lock:
+            self._value -= num
+            return self._value
+
+    @property
+    def value(self):
+        return self._value
+
+
+if __name__ == "__main__":
+    import doctest
+
+    doctest.testmod()
diff --git a/environment.yml b/environment.yml
index df4382d..33f2bd3 100644
--- a/environment.yml
+++ b/environment.yml
@@ -1,6 +1,7 @@
-name: abb-egm-examples
+name: abb-egm-examples1
 channels:
   - conda-forge
 dependencies:
+  - python >=3.9, <3.10
   - numpy
   - protobuf
diff --git a/pyproject.toml b/pyproject.toml
index 9ac9b91..a8df0f8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,3 +4,6 @@ requires = [
   "wheel",
 ]
 build-backend = "setuptools.build_meta"
+
+[tool.isort]
+profile = "black"
diff --git a/setup.cfg b/setup.cfg
index d267f5d..d2f3dc6 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,6 +4,16 @@ version = 0.1.0
 
 [options]
 packages = abb_egm_client
-python_requires = >= 3.8
+python_requires = >= 3.9
 install_requires =
     protobuf
+
+[options.extras_require]
+dev = 
+    black
+    flake8
+    isort >= 5.0.0
+
+[flake8]
+max-line-length = 88
+extend-ignore = E203
-- 
GitLab