mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-30 00:00:11 +01:00
python: flake8 liniting
This commit is contained in:
parent
c7fd20e478
commit
f6ef7265ce
7 changed files with 177 additions and 142 deletions
|
@ -1,4 +1,3 @@
|
|||
import os
|
||||
from setuptools import setup, find_namespace_packages
|
||||
from glob import glob
|
||||
|
||||
|
@ -6,33 +5,33 @@ with open('README.md') as f:
|
|||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name = 'villas-node',
|
||||
version = '0.10.0',
|
||||
author = 'Steffen Vogel',
|
||||
author_email = 'acs-software@eonerc.rwth-aachen.de',
|
||||
description = 'Python-support for VILLASnode simulation-data gateway',
|
||||
license = 'GPL-3.0',
|
||||
keywords = 'simulation power system real-time villas',
|
||||
url = 'https://git.rwth-aachen.de/acs/public/villas/VILLASnode',
|
||||
packages = find_namespace_packages(include=['villas.*']),
|
||||
long_description = long_description,
|
||||
long_description_content_type = 'text/markdown',
|
||||
classifiers = [
|
||||
name='villas-node',
|
||||
version='0.10.0',
|
||||
author='Steffen Vogel',
|
||||
author_email='acs-software@eonerc.rwth-aachen.de',
|
||||
description='Python-support for VILLASnode simulation-data gateway',
|
||||
license='GPL-3.0',
|
||||
keywords='simulation power system real-time villas',
|
||||
url='https://git.rwth-aachen.de/acs/public/villas/VILLASnode',
|
||||
packages=find_namespace_packages(include=['villas.*']),
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/markdown',
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Topic :: Scientific/Engineering',
|
||||
'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
|
||||
'License :: OSI Approved :: '
|
||||
'GNU General Public License v3 or later (GPLv3+)',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Programming Language :: Python :: 3'
|
||||
],
|
||||
install_requires = [
|
||||
install_requires=[
|
||||
'requests',
|
||||
'linuxfd'
|
||||
],
|
||||
setup_requires = [
|
||||
setup_requires=[
|
||||
'm2r'
|
||||
],
|
||||
scripts = glob('bin/*')
|
||||
scripts=glob('bin/*')
|
||||
)
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
from message import Message
|
||||
from timestamp import Timestamp
|
||||
from message import Message # noqa F401
|
||||
from timestamp import Timestamp # noqa F401
|
||||
|
|
|
@ -1,24 +1,30 @@
|
|||
import .timestamp
|
||||
import villas.human.timestamp as ts
|
||||
from functools import total_ordering
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Message:
|
||||
"""Parsing a VILLASnode sample from a file (not a UDP package!!)"""
|
||||
"""Parsing a VILLASnode sample from a file (not a UDP package!!)"""
|
||||
|
||||
def __init__(self, ts, values, source = None):
|
||||
self.source = source
|
||||
self.ts = ts
|
||||
self.values = values
|
||||
def __init__(self, ts, values, source=None):
|
||||
self.source = source
|
||||
self.ts = ts
|
||||
self.values = values
|
||||
|
||||
@classmethod
|
||||
def parse(self, line, source = None):
|
||||
csv = line.split()
|
||||
@classmethod
|
||||
def parse(cls, line, source=None):
|
||||
csv = line.split()
|
||||
|
||||
t = ts.Timestamp.parse(csv[0])
|
||||
v = map(float, csv[1:])
|
||||
t = ts.Timestamp.parse(csv[0])
|
||||
v = map(float, csv[1:])
|
||||
|
||||
return Message(t, v, source)
|
||||
return Message(t, v, source)
|
||||
|
||||
def __str__(self):
|
||||
return '%s %s' % (self.ts, " ".join(map(str, self.values)))
|
||||
def __str__(self):
|
||||
return '%s %s' % (self.ts, " ".join(map(str, self.values)))
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.ts, other.ts)
|
||||
def __eq__(self, other):
|
||||
return self.ts == other.ts
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.ts < other.ts
|
||||
|
|
|
@ -1,46 +1,54 @@
|
|||
import re
|
||||
from functools import total_ordering
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Timestamp:
|
||||
"""Parsing the VILLASnode human-readable timestamp format"""
|
||||
"""Parsing the VILLASnode human-readable timestamp format"""
|
||||
|
||||
def __init__(self, seconds = 0, nanoseconds = None, offset = None, sequence = None):
|
||||
self.seconds = seconds
|
||||
self.nanoseconds = nanoseconds
|
||||
self.offset = offset
|
||||
self.sequence = sequence
|
||||
def __init__(self, seconds=0, nanoseconds=None,
|
||||
offset=None, sequence=None):
|
||||
self.seconds = seconds
|
||||
self.nanoseconds = nanoseconds
|
||||
self.offset = offset
|
||||
self.sequence = sequence
|
||||
|
||||
@classmethod
|
||||
def parse(self, ts):
|
||||
m = re.match('(\d+)(?:\.(\d+))?([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))?', ts)
|
||||
@classmethod
|
||||
def parse(cls, ts):
|
||||
m = re.match(r'(\d+)(?:\.(\d+))?([-+]\d+(?:\.\d+)?'
|
||||
r'(?:e[+-]?\d+)?)?(?:\((\d+)\))?', ts)
|
||||
|
||||
seconds = int(m.group(1)); # Mandatory
|
||||
nanoseconds = int(m.group(2)) if m.group(2) else None
|
||||
offset = float(m.group(3)) if m.group(3) else None
|
||||
sequence = int(m.group(4)) if m.group(4) else None
|
||||
seconds = int(m.group(1)) # Mandatory
|
||||
nanoseconds = int(m.group(2)) if m.group(2) else None
|
||||
offset = float(m.group(3)) if m.group(3) else None
|
||||
sequence = int(m.group(4)) if m.group(4) else None
|
||||
|
||||
return Timestamp(seconds, nanoseconds, offset, sequence)
|
||||
return Timestamp(seconds, nanoseconds, offset, sequence)
|
||||
|
||||
def __str__(self):
|
||||
str = "%u" % (self.seconds)
|
||||
def __str__(self):
|
||||
str = "%u" % (self.seconds)
|
||||
|
||||
if self.nanoseconds is not None:
|
||||
str += ".%09u" % self.nanoseconds
|
||||
if self.offset is not None:
|
||||
str += "+%u" % self.offset
|
||||
if self.sequence is not None:
|
||||
str += "(%u)" % self.sequence
|
||||
if self.nanoseconds is not None:
|
||||
str += ".%09u" % self.nanoseconds
|
||||
if self.offset is not None:
|
||||
str += "+%u" % self.offset
|
||||
if self.sequence is not None:
|
||||
str += "(%u)" % self.sequence
|
||||
|
||||
return str
|
||||
return str
|
||||
|
||||
def __float__(self):
|
||||
sum = float(self.seconds)
|
||||
def __float__(self):
|
||||
sum = float(self.seconds)
|
||||
|
||||
if self.nanoseconds is not None:
|
||||
sum += self.nanoseconds * 1e-9
|
||||
if self.offset is not None:
|
||||
sum += self.offset
|
||||
if self.nanoseconds is not None:
|
||||
sum += self.nanoseconds * 1e-9
|
||||
if self.offset is not None:
|
||||
sum += self.offset
|
||||
|
||||
return sum
|
||||
return sum
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(float(self), float(other))
|
||||
def __eg__(self, other):
|
||||
return float(self) == float(other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return float(self) < float(other)
|
||||
|
|
|
@ -7,6 +7,7 @@ from threading import Thread
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RecvThread(Thread):
|
||||
|
||||
def __init__(self, cb):
|
||||
|
@ -78,4 +79,4 @@ def communicate(rate, recv_cb=None, send_cb=None, wait=True):
|
|||
logger.info('Received Ctrl+C. Stopping send/recv threads')
|
||||
|
||||
# Threads are daemon threads
|
||||
# and therefore killed with program termination
|
||||
# and therefore killed with program termination
|
||||
|
|
|
@ -9,9 +9,12 @@ import datetime
|
|||
|
||||
LOGGER = logging.getLogger('villas.node')
|
||||
|
||||
|
||||
class Node(object):
|
||||
|
||||
def __init__(self, log_filename = None, config_filename = None, config = { }, api = 'http://localhost:8080', executable = 'villas-node', **kwargs):
|
||||
def __init__(self, log_filename=None, config_filename=None,
|
||||
config={}, api='http://localhost:8080',
|
||||
executable='villas-node', **kwargs):
|
||||
self.config = config
|
||||
self.config_filename = config_filename
|
||||
self.log_filename = log_filename
|
||||
|
@ -21,7 +24,8 @@ class Node(object):
|
|||
self.child = None
|
||||
|
||||
def start(self):
|
||||
self.config_file = tempfile.NamedTemporaryFile(mode='w+', suffix='.json')
|
||||
self.config_file = tempfile.NamedTemporaryFile(mode='w+',
|
||||
suffix='.json')
|
||||
|
||||
if self.config_filename:
|
||||
with open(self.config_filename) as f:
|
||||
|
@ -33,13 +37,16 @@ class Node(object):
|
|||
|
||||
if self.log_filename is None:
|
||||
now = datetime.datetime.now()
|
||||
self.log_filename = now.strftime('villas-node_%Y-%m-%d_%H-%M-%S.log')
|
||||
self.log_filename = now.strftime(
|
||||
'villas-node_%Y-%m-%d_%H-%M-%S.log')
|
||||
|
||||
self.log = open(self.log_filename, 'w+')
|
||||
|
||||
LOGGER.info("Starting VILLASnode instance with config: %s", self.config_file.name)
|
||||
LOGGER.info("Starting VILLASnode instance with config: %s",
|
||||
self.config_file.name)
|
||||
|
||||
self.child = subprocess.Popen([self.executable, self.config_file.name], stdout=self.log, stderr=self.log)
|
||||
self.child = subprocess.Popen([self.executable, self.config_file.name],
|
||||
stdout=self.log, stderr=self.log)
|
||||
|
||||
def pause(self):
|
||||
LOGGER.info("Pausing VILLASnode instance")
|
||||
|
@ -74,10 +81,10 @@ class Node(object):
|
|||
def paths(self):
|
||||
return self.request('paths')['response']
|
||||
|
||||
def request(self, action, req = None):
|
||||
def request(self, action, req=None):
|
||||
body = {
|
||||
'action' : action,
|
||||
'id' : str(uuid.uuid4())
|
||||
'action': action,
|
||||
'id': str(uuid.uuid4())
|
||||
}
|
||||
|
||||
if req is not None:
|
||||
|
|
|
@ -1,93 +1,107 @@
|
|||
import re
|
||||
from datetime import datetime
|
||||
from functools import total_ordering
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Timestamp:
|
||||
"""Parsing the VILLASnode human-readable timestamp format"""
|
||||
"""Parsing the VILLASnode human-readable timestamp format"""
|
||||
|
||||
def __init__(self, seconds=None, nanoseconds=None, offset=None, sequence=None):
|
||||
self.seconds = seconds
|
||||
self.nanoseconds = nanoseconds
|
||||
self.offset = offset
|
||||
self.sequence = sequence
|
||||
def __init__(self, seconds=None, nanoseconds=None,
|
||||
offset=None, sequence=None):
|
||||
self.seconds = seconds
|
||||
self.nanoseconds = nanoseconds
|
||||
self.offset = offset
|
||||
self.sequence = sequence
|
||||
|
||||
@classmethod
|
||||
def now(self, offset=None, sequence=None):
|
||||
n = datetime.utcnow()
|
||||
@classmethod
|
||||
def now(cls, offset=None, sequence=None):
|
||||
n = datetime.utcnow()
|
||||
|
||||
secs = int(n.timestamp())
|
||||
nsecs = 1000 * n.microsecond
|
||||
secs = int(n.timestamp())
|
||||
nsecs = 1000 * n.microsecond
|
||||
|
||||
return Timestamp(seconds=secs, nanoseconds=nsecs, offset=offset, sequence=sequence)
|
||||
return Timestamp(seconds=secs, nanoseconds=nsecs,
|
||||
offset=offset, sequence=sequence)
|
||||
|
||||
@classmethod
|
||||
def parse(self, ts):
|
||||
m = re.match('(\d+)(?:\.(\d+))?([-+]\d+(?:\.\d+)?(?:e[+-]?\d+)?)?(?:\((\d+)\))?', ts)
|
||||
@classmethod
|
||||
def parse(cls, ts):
|
||||
m = re.match(r'(\d+)(?:\.(\d+))?([-+]\d+(?:\.\d+)?'
|
||||
r'(?:e[+-]?\d+)?)?(?:\((\d+)\))?', ts)
|
||||
|
||||
seconds = int(m.group(1)); # Mandatory
|
||||
nanoseconds = int(m.group(2)) if m.group(2) else None
|
||||
offset = float(m.group(3)) if m.group(3) else None
|
||||
sequence = int(m.group(4)) if m.group(4) else None
|
||||
seconds = int(m.group(1)) # Mandatory
|
||||
nanoseconds = int(m.group(2)) if m.group(2) else None
|
||||
offset = float(m.group(3)) if m.group(3) else None
|
||||
sequence = int(m.group(4)) if m.group(4) else None
|
||||
|
||||
return Timestamp(seconds, nanoseconds, offset, sequence)
|
||||
return Timestamp(seconds, nanoseconds, offset, sequence)
|
||||
|
||||
def __str__(self):
|
||||
str = "%u" % (self.seconds)
|
||||
def __str__(self):
|
||||
str = "%u" % (self.seconds)
|
||||
|
||||
if self.nanoseconds is not None:
|
||||
str += ".%09u" % self.nanoseconds
|
||||
if self.offset is not None:
|
||||
str += "+%u" % self.offset
|
||||
if self.sequence is not None:
|
||||
str += "(%u)" % self.sequence
|
||||
if self.nanoseconds is not None:
|
||||
str += ".%09u" % self.nanoseconds
|
||||
if self.offset is not None:
|
||||
str += "+%u" % self.offset
|
||||
if self.sequence is not None:
|
||||
str += "(%u)" % self.sequence
|
||||
|
||||
return str
|
||||
return str
|
||||
|
||||
def __float__(self):
|
||||
sum = float(self.seconds)
|
||||
def __float__(self):
|
||||
sum = float(self.seconds)
|
||||
|
||||
if self.nanoseconds is not None:
|
||||
sum += self.nanoseconds * 1e-9
|
||||
if self.offset is not None:
|
||||
sum += self.offset
|
||||
if self.nanoseconds is not None:
|
||||
sum += self.nanoseconds * 1e-9
|
||||
if self.offset is not None:
|
||||
sum += self.offset
|
||||
|
||||
return sum
|
||||
return sum
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(float(self), float(other))
|
||||
def __eq__(self, other):
|
||||
return float(self) == float(other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return float(self) < float(other)
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Sample:
|
||||
"""Parsing a VILLASnode sample from a file (not a UDP package!!)"""
|
||||
"""Parsing a VILLASnode sample from a file (not a UDP package!!)"""
|
||||
|
||||
def __init__(self, ts, values):
|
||||
self.ts = ts
|
||||
self.values = values
|
||||
def __init__(self, ts, values):
|
||||
self.ts = ts
|
||||
self.values = values
|
||||
|
||||
@classmethod
|
||||
def parse(self, line):
|
||||
csv = line.split()
|
||||
@classmethod
|
||||
def parse(cls, line):
|
||||
csv = line.split()
|
||||
|
||||
ts = Timestamp.parse(csv[0])
|
||||
vs = [ ]
|
||||
ts = Timestamp.parse(csv[0])
|
||||
vs = []
|
||||
|
||||
for value in csv[1:]:
|
||||
try:
|
||||
v = float(value)
|
||||
except ValueError:
|
||||
value = value.lower()
|
||||
try:
|
||||
v = complex(value)
|
||||
except:
|
||||
if value.endswith('i'):
|
||||
v = complex(value.replace('i', 'j'))
|
||||
else:
|
||||
raise ValueError()
|
||||
for value in csv[1:]:
|
||||
try:
|
||||
v = float(value)
|
||||
except ValueError:
|
||||
value = value.lower()
|
||||
try:
|
||||
v = complex(value)
|
||||
except Exception:
|
||||
if value.endswith('i'):
|
||||
v = complex(value.replace('i', 'j'))
|
||||
else:
|
||||
raise ValueError()
|
||||
|
||||
vs.append(v)
|
||||
vs.append(v)
|
||||
|
||||
return Sample(ts, vs)
|
||||
return Sample(ts, vs)
|
||||
|
||||
def __str__(self):
|
||||
return '%s %s' % (self.ts, " ".join(map(str, self.values)))
|
||||
def __str__(self):
|
||||
return '%s %s' % (self.ts, " ".join(map(str, self.values)))
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.ts, other.ts)
|
||||
def __eq__(self, other):
|
||||
return self.ts == other.ts
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.ts < other.ts
|
||||
|
|
Loading…
Add table
Reference in a new issue