Skip to content

Commit c829663

Browse files
authored
Merge pull request #90 from lpsinger/black
Add black code formatter
2 parents f72d406 + adcf935 commit c829663

File tree

10 files changed

+193
-66
lines changed

10 files changed

+193
-66
lines changed

.flake8

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[flake8]
2+
max-line-length = 88
3+
extend-ignore = E203, E704

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ jobs:
2929
- name: Checkout repository
3030
uses: actions/checkout@v4
3131

32+
- uses: psf/black@stable
33+
3234
- name: Set up Python ${{ matrix.python-version }}
3335
uses: actions/setup-python@v5
3436
with:

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"editor.defaultFormatter": "ms-python.black-formatter",
3+
"python.testing.unittestEnabled": false,
4+
"python.testing.pytestEnabled": true
5+
}

gcn_classic_to_kafka/cli.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424

2525
def signal_handler(signum, frame):
26-
log.info('Exiting due to signal %d', signum)
26+
log.info("Exiting due to signal %d", signum)
2727
sys.exit(128 + signum)
2828

2929

@@ -36,19 +36,31 @@ def host_port(host_port_str):
3636
# Parse netloc like it is done for HTTP URLs.
3737
# This ensures that we will get the correct behavior for hostname:port
3838
# splitting even for IPv6 addresses.
39-
return urllib.parse.urlparse(f'http://{host_port_str}')
39+
return urllib.parse.urlparse(f"http://{host_port_str}")
4040

4141

4242
@click.command()
4343
@click.option(
44-
'--listen', type=host_port, default=':8081', show_default=True,
45-
help='Hostname and port to listen on for GCN Classic')
44+
"--listen",
45+
type=host_port,
46+
default=":8081",
47+
show_default=True,
48+
help="Hostname and port to listen on for GCN Classic",
49+
)
4650
@click.option(
47-
'--prometheus', type=host_port, default=':8000', show_default=True,
48-
help='Hostname and port to listen on for Prometheus metric reporting')
51+
"--prometheus",
52+
type=host_port,
53+
default=":8000",
54+
show_default=True,
55+
help="Hostname and port to listen on for Prometheus metric reporting",
56+
)
4957
@click.option(
50-
'--loglevel', type=click.Choice(logging._levelToName.values()),
51-
default='DEBUG', show_default=True, help='Log level')
58+
"--loglevel",
59+
type=click.Choice(logging._levelToName.values()),
60+
default="DEBUG",
61+
show_default=True,
62+
help="Log level",
63+
)
5264
def main(listen, prometheus, loglevel):
5365
"""Pump GCN Classic notices to a Kafka broker.
5466
@@ -64,21 +76,21 @@ def main(listen, prometheus, loglevel):
6476
"""
6577
logging.basicConfig(level=loglevel)
6678

67-
prometheus_client.start_http_server(prometheus.port,
68-
prometheus.hostname or '0.0.0.0')
69-
log.info('Prometheus listening on %s', prometheus.netloc)
79+
prometheus_client.start_http_server(
80+
prometheus.port, prometheus.hostname or "0.0.0.0"
81+
)
82+
log.info("Prometheus listening on %s", prometheus.netloc)
7083

7184
config = gcn_kafka.config_from_env()
72-
config['client.id'] = __package__
73-
config['on_delivery'] = kafka_delivered_cb
85+
config["client.id"] = __package__
86+
config["on_delivery"] = kafka_delivered_cb
7487

7588
producer = gcn_kafka.Producer(config)
7689
client = client_connected(producer)
7790

7891
async def serve():
79-
server = await asyncio.start_server(
80-
client, listen.hostname, listen.port)
81-
log.info('GCN server listening on %s', listen.netloc)
92+
server = await asyncio.start_server(client, listen.hostname, listen.port)
93+
log.info("GCN server listening on %s", listen.netloc)
8294
async with server:
8395
await server.serve_forever()
8496

gcn_classic_to_kafka/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def notice_type_int_to_str(notice_type_int):
3838
try:
3939
notice_type_enum = gcn.NoticeType(notice_type_int)
4040
except ValueError:
41-
notice_type_str = 'UNKNOWN'
41+
notice_type_str = "UNKNOWN"
4242
else:
4343
notice_type_str = notice_type_enum.name
4444
return notice_type_str
@@ -66,4 +66,4 @@ def topic_for_notice_type_str(notice_type_str, flavor):
6666
'gcn.classic.voevent.LVC_PRELIMINARY'
6767
6868
"""
69-
return f'gcn.classic.{flavor}.{notice_type_str}'
69+
return f"gcn.classic.{flavor}.{notice_type_str}"

gcn_classic_to_kafka/metrics.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,25 @@
99
import prometheus_client
1010

1111
connected = prometheus_client.Gauge(
12-
'connected', 'Number of active connections from GCN Classic',
13-
namespace=__package__)
12+
"connected", "Number of active connections from GCN Classic", namespace=__package__
13+
)
1414

1515
iamalive = prometheus_client.Counter(
16-
'iamalive',
17-
'GCN notices received of any type, including iamalives',
18-
namespace=__package__)
16+
"iamalive",
17+
"GCN notices received of any type, including iamalives",
18+
namespace=__package__,
19+
)
1920

2021
received = prometheus_client.Counter(
21-
'received',
22-
'GCN Classic notices received by notice type and flavor',
23-
labelnames=['notice_type_int', 'notice_type_str', 'flavor'],
24-
namespace=__package__)
22+
"received",
23+
"GCN Classic notices received by notice type and flavor",
24+
labelnames=["notice_type_int", "notice_type_str", "flavor"],
25+
namespace=__package__,
26+
)
2527

2628
delivered = prometheus_client.Counter(
27-
'delivered',
28-
'Kafka messages delivered',
29-
labelnames=['topic', 'partition', 'successful'],
30-
namespace=__package__)
29+
"delivered",
30+
"Kafka messages delivered",
31+
labelnames=["topic", "partition", "successful"],
32+
namespace=__package__,
33+
)

gcn_classic_to_kafka/socket.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,34 @@
2020
log = logging.getLogger(__name__)
2121

2222
bin_len = 160
23-
int4 = struct.Struct('!l')
24-
ignore_notice_types = {gcn.NoticeType.IM_ALIVE,
25-
gcn.NoticeType.VOE_11_IM_ALIVE,
26-
gcn.NoticeType.VOE_20_IM_ALIVE}
23+
int4 = struct.Struct("!l")
24+
ignore_notice_types = {
25+
gcn.NoticeType.IM_ALIVE,
26+
gcn.NoticeType.VOE_11_IM_ALIVE,
27+
gcn.NoticeType.VOE_20_IM_ALIVE,
28+
}
2729

2830

2931
def client_connected(producer: confluent_kafka.Producer, timeout: float = 90):
3032

31-
async def client_connected_cb(reader: asyncio.StreamReader,
32-
writer: asyncio.StreamWriter):
33+
async def client_connected_cb(
34+
reader: asyncio.StreamReader, writer: asyncio.StreamWriter
35+
):
3336
async def read():
3437
bin_data = await reader.readexactly(bin_len)
35-
voe_len, = int4.unpack(await reader.readexactly(int4.size))
38+
(voe_len,) = int4.unpack(await reader.readexactly(int4.size))
3639
voe_data = await reader.readexactly(voe_len)
37-
txt_len, = int4.unpack(await reader.readexactly(int4.size))
40+
(txt_len,) = int4.unpack(await reader.readexactly(int4.size))
3841
txt_data = await reader.readexactly(txt_len)
39-
log.debug('Read %d + %d + %d bytes', bin_len, voe_len, txt_len)
42+
log.debug("Read %d + %d + %d bytes", bin_len, voe_len, txt_len)
4043
return bin_data, voe_data, txt_data
4144

4245
async def process():
43-
bin_data, voe_data, txt_data = await asyncio.wait_for(
44-
read(), timeout)
46+
bin_data, voe_data, txt_data = await asyncio.wait_for(read(), timeout)
4547
metrics.iamalive.inc()
4648

47-
bin_notice_type, = int4.unpack_from(bin_data)
48-
log.info('Received notice of type 0x%08X', bin_notice_type)
49+
(bin_notice_type,) = int4.unpack_from(bin_data)
50+
log.info("Received notice of type 0x%08X", bin_notice_type)
4951
if bin_notice_type in ignore_notice_types:
5052
return
5153

@@ -54,35 +56,36 @@ async def process():
5456

5557
if bin_notice_type != voe_notice_type:
5658
log.warning(
57-
'Binary (0x%08X) and VOEvent (0x%08X) notice types differ',
58-
bin_notice_type, voe_notice_type)
59+
"Binary (0x%08X) and VOEvent (0x%08X) notice types differ",
60+
bin_notice_type,
61+
voe_notice_type,
62+
)
5963

6064
# The text notices do not contain a machine-readable notice type.
6165
txt_notice_type = bin_notice_type
6266

6367
for notice_type_int, data, flavor in [
64-
[bin_notice_type, bin_data, 'binary'],
65-
[voe_notice_type, voe_data, 'voevent'],
66-
[txt_notice_type, txt_data, 'text'],
68+
[bin_notice_type, bin_data, "binary"],
69+
[voe_notice_type, voe_data, "voevent"],
70+
[txt_notice_type, txt_data, "text"],
6771
]:
6872
notice_type_str = notice_type_int_to_str(notice_type_int)
69-
metrics.received.labels(
70-
notice_type_int, notice_type_str, flavor).inc()
73+
metrics.received.labels(notice_type_int, notice_type_str, flavor).inc()
7174
topic = topic_for_notice_type_str(notice_type_str, flavor)
7275
producer.produce(topic, data)
7376

7477
# Wait for any outstanding messages to be delivered and delivery
7578
# report callbacks to be triggered.
7679
producer.poll(0)
7780

78-
peer, *_ = writer.get_extra_info('peername')
79-
log.info('Client connected from %s', peer)
81+
peer, *_ = writer.get_extra_info("peername")
82+
log.info("Client connected from %s", peer)
8083
try:
8184
with metrics.connected.track_inprogress():
8285
while True:
8386
await process()
8487
finally:
85-
log.info('Closing connection from %s', peer)
88+
log.info("Closing connection from %s", peer)
8689
writer.close()
8790
await writer.wait_closed()
8891

gcn_classic_to_kafka/test/test_socket.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,24 @@ def make_packet(bin_notice_type, voe_notice_type=None):
3434
</What>
3535
</voe:VOEvent>
3636
""".encode()
37-
text = b'Hello world'
37+
text = b"Hello world"
3838
return (
39-
struct.pack('!l156xl', bin_notice_type, len(voevent)) + voevent +
40-
struct.pack('!l', len(text)) + text)
39+
struct.pack("!l156xl", bin_notice_type, len(voevent))
40+
+ voevent
41+
+ struct.pack("!l", len(text))
42+
+ text
43+
)
4144

4245

4346
@pytest_asyncio.fixture
4447
async def start_server():
4548
producer = mock.Mock()
4649
cb = client_connected(producer=producer, timeout=timeout)
47-
server = await asyncio.start_server(cb, '127.0.0.1')
50+
server = await asyncio.start_server(cb, "127.0.0.1")
4851

4952
async with server:
5053
server_task = asyncio.create_task(server.serve_forever())
51-
socket, = server.sockets
54+
(socket,) = server.sockets
5255
host, port = socket.getsockname()
5356
yield producer, host, port
5457
server_task.cancel()
@@ -96,10 +99,13 @@ async def test_socket(start_server):
9699
await writer.drain()
97100
await asyncio.sleep(0.25 * timeout)
98101
assert not reader.at_eof()
99-
producer.produce.assert_has_calls([
100-
mock.call('gcn.classic.binary.LVC_TEST', mock.ANY),
101-
mock.call('gcn.classic.voevent.LVC_TEST', mock.ANY),
102-
mock.call('gcn.classic.text.LVC_TEST', mock.ANY)])
102+
producer.produce.assert_has_calls(
103+
[
104+
mock.call("gcn.classic.binary.LVC_TEST", mock.ANY),
105+
mock.call("gcn.classic.voevent.LVC_TEST", mock.ANY),
106+
mock.call("gcn.classic.text.LVC_TEST", mock.ANY),
107+
]
108+
)
103109

104110
writer.close()
105111
await writer.wait_closed()

0 commit comments

Comments
 (0)