ex 8.1, 8.2, 8.3

This commit is contained in:
Mike Bloy 2024-01-21 13:10:31 -06:00
parent 1f4b203f61
commit a9077d8308
6 changed files with 155 additions and 1 deletions

1
.gitignore vendored
View File

@ -159,3 +159,4 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
Session.vim
Data/stocklog.csv

34
cofollow.py Normal file
View File

@ -0,0 +1,34 @@
import os
import time
from functools import wraps
def follow(filename, target):
with open(filename, 'r') as f:
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if line != '':
target.send(line)
else:
time.sleep(0.1)
def consumer(func):
@wraps(func)
def start(*args, **kwargs):
f = func(*args, **kwargs)
f.send(None)
return f
return start
@consumer
def printer():
while True:
item = yield
print(item)
if __name__ == '__main__':
follow('Data/stocklog.csv', printer())

57
coticker.py Normal file
View File

@ -0,0 +1,57 @@
import csv
from cofollow import consumer
from tableformat import create_formatter
from ticker import Ticker
@consumer
def to_csv(target):
def producer():
while True:
yield line
reader = csv.reader(producer())
while True:
line = yield
target.send(next(reader))
@consumer
def create_ticker(target):
while True:
row = yield
target.send(Ticker.from_row(row))
@consumer
def negchange(target):
while True:
record = yield
if record.change < 0:
target.send(record)
@consumer
def ticker(fmt, fields):
formatter = create_formatter(fmt)
formatter.headings(fields)
while True:
rec = yield
row = [getattr(rec, name) for name in fields]
formatter.row(row)
if __name__ == '__main__':
from cofollow import follow
follow(
'Data/stocklog.csv',
to_csv(
create_ticker(
negchange(
ticker('text', ['name', 'price', 'change'])
)
)
)
)

23
follow.py Normal file
View File

@ -0,0 +1,23 @@
import os
import time
def follow(filename):
f = open(filename)
f.seek(0, os.SEEK_END)
while True:
line = f.readline()
if line == '':
time.sleep(0.1)
continue
yield line
if __name__ == '__main__':
for line in follow('Data/stocklog.csv'):
fields = line.split(',')
name = fields[0].strip('"')
price = float(fields[1])
change = float(fields[4])
if change < 0:
print(f"{name:s} {price:10.2f} {change:10.2f}")

View File

@ -35,7 +35,7 @@ class Structure(metaclass=StructureMeta):
validate_attributes(cls)
def __repr__(self):
args = map(lambda field: f"{field}={getattr(self, field)!r}", self._fields)
args = map(lambda field: f"{getattr(self, field)!r}", self._fields)
return f"{type(self).__name__}({', '.join(args)})"
def __setattr__(self, name, value):
@ -44,6 +44,13 @@ class Structure(metaclass=StructureMeta):
else:
raise AttributeError(f"No attribute {name}")
def __iter__(self):
for name in self._fields:
yield getattr(self, name)
def __eq__(self, other):
return isinstance(other, type(self)) and tuple(self) == tuple(other)
@classmethod
def create_init(cls):
code = f'def __init__(self, {", ".join(cls._fields)}):\n'
@ -53,6 +60,10 @@ class Structure(metaclass=StructureMeta):
exec(code, locs)
cls.__init__ = locs['__init__']
@classmethod
def from_row(cls, row):
return cls(*[func(val) for func, val in zip(cls._types, row)])
def typed_structure(clsname, **validators):
cls = type(clsname, (Structure,), validators)

28
ticker.py Normal file
View File

@ -0,0 +1,28 @@
from structure import Structure
class Ticker(Structure):
name = String()
price = Float()
date = String()
time = String()
change = Float()
open = Float()
high = Float()
low = Float()
volume = Integer()
if __name__ == '__main__':
import csv
from follow import follow
from tableformat import create_formatter, print_table
formatter = create_formatter('text')
lines = follow('Data/stocklog.csv')
rows = csv.reader(lines)
records = (Ticker.from_row(row) for row in rows)
negative = (rec for rec in records if rec.change < 0)
print_table(negative, ['name', 'price', 'change'], formatter)