This is an automated email from the ASF dual-hosted git repository.
gstein pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/steve.git
The following commit(s) were added to refs/heads/trunk by this push:
new 9bf0c73 Tweaks for dealing with PersonDB
9bf0c73 is described below
commit 9bf0c7372f8b891bfaf6017ab9a3b9371854163c
Author: Greg Stein <[email protected]>
AuthorDate: Fri Feb 6 08:50:43 2026 -0600
Tweaks for dealing with PersonDB
The addition of PersonDB means there can (now) be two SQLite
connections open to the database. This made create-election.py fail
because both connections were trying to write (specifically, a
transaction was started, which created a lock, with foreclosed the
other connection).
Fix: PersonDB now takes a DB instance in its constructor. There is a
new class method to open() a filename for the DB and the PersonDB
instance.
TBD: the getattr/cursor attributes on the DB instance are not correct
for both usages.
* persondb.py: add the classmethod
* create-election:
- add #! to make this executable
- revise transaction management
- share the DB between the instances
- hack in q_person cursor
* asf-load-ldap, pages, check_coverage: switch to PersonDB.open()
---
v3/server/bin/asf-load-ldap.py | 2 +-
v3/server/bin/create-election.py | 28 ++++++++++++++++++++++++----
v3/server/pages.py | 4 ++--
v3/steve/persondb.py | 11 +++++++++--
v3/tests/check_coverage.py | 2 +-
5 files changed, 37 insertions(+), 10 deletions(-)
diff --git a/v3/server/bin/asf-load-ldap.py b/v3/server/bin/asf-load-ldap.py
index d5faefb..ab4ba46 100755
--- a/v3/server/bin/asf-load-ldap.py
+++ b/v3/server/bin/asf-load-ldap.py
@@ -39,7 +39,7 @@ LDAP_ATTR = 'memberUid'
@asfpy.stopwatch.Stopwatch()
def main():
- pdb = steve.persondb.PersonDB(DB_FNAME)
+ pdb = steve.persondb.PersonDB.open(DB_FNAME)
# Reach into PDB for the CONN, and start a transaction for all
# of the inserts we will perform. (rather than default auto-commit)
pdb.db.conn.execute('BEGIN TRANSACTION')
diff --git a/v3/server/bin/create-election.py b/v3/server/bin/create-election.py
old mode 100644
new mode 100755
index d3235f1..c922dfd
--- a/v3/server/bin/create-election.py
+++ b/v3/server/bin/create-election.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -32,6 +34,7 @@ DB_FNAME = THIS_DIR.parent / 'steve.db'
# Supported vote types
VALID_VTYPES = {'yna', 'stv'}
+
def parse_datetime(dt_str):
"""Parse ISO datetime string to Unix timestamp."""
if not dt_str:
@@ -39,6 +42,7 @@ def parse_datetime(dt_str):
dt = datetime.datetime.fromisoformat(dt_str)
return int(dt.timestamp())
+
def validate_issue(issue):
"""Validate an issue dict from YAML."""
if 'vtype' not in issue or issue['vtype'] not in VALID_VTYPES:
@@ -51,6 +55,7 @@ def validate_issue(issue):
raise ValueError("STV seats must be a positive integer")
return issue
+
def main(yaml_file):
with open(yaml_file, 'r') as f:
data = yaml.safe_load(f)
@@ -76,9 +81,12 @@ def main(yaml_file):
if eligible_voters != 'members':
raise ValueError("Only 'members' is supported for eligible_voters")
+ ### revising how we manage the two database instances and their
+ ### connections. no transactions for now. partial Elections, and
+ ### issues are fine for now.
# Start transaction for safety
- pdb = steve.persondb.PersonDB(DB_FNAME)
- pdb.db.conn.execute('BEGIN TRANSACTION')
+ #pdb = steve.persondb.PersonDB(DB_FNAME)
+ #pdb.db.conn.execute('BEGIN TRANSACTION')
try:
# Create election
@@ -95,20 +103,32 @@ def main(yaml_file):
)
_LOGGER.info(f'Added issue[I:{iid}] to election[E:{election.eid}]')
+ # Open a PersonDB using the existing DB from the Election
+ pdb = steve.persondb.PersonDB(election.db)
+
+ ### HACK: we opened PDB using the existing DB from the Election.
+ ### It does not have the cursors specific to PersonDB. For now,
+ ### hack the bugger in.
+ ### q_person: SELECT * FROM person ORDER BY pid
+ pdb.q_person = pdb.db.cursor_for('SELECT * FROM person ORDER BY pid')
+
# Add voters: All persons in persondb to all issues
all_persons = pdb.list_persons()
for person in all_persons:
election.add_voter(person.pid)
_LOGGER.info(f'Added {len(all_persons)} voters to
election[E:{election.eid}]')
- pdb.db.conn.execute('COMMIT')
+ ### we aren't doing transactions right now. omit this.
+ #pdb.db.conn.execute('COMMIT')
_LOGGER.info(f'Election[E:{election.eid}] fully created from
{yaml_file}')
except Exception as e:
- pdb.db.conn.execute('ROLLBACK')
+ ### we aren't doing transactions right now. omit this.
+ #pdb.db.conn.execute('ROLLBACK')
_LOGGER.error(f'Failed to create election from {yaml_file}: {e}')
raise
+
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
diff --git a/v3/server/pages.py b/v3/server/pages.py
index 55d98c5..65f7683 100644
--- a/v3/server/pages.py
+++ b/v3/server/pages.py
@@ -235,7 +235,7 @@ async def admin_page():
### "me" because of authz access to manage issues.
### should open/keep a PersonDB instance in the APP
- pdb = steve.persondb.PersonDB(DB_FNAME)
+ pdb = steve.persondb.PersonDB.open(DB_FNAME)
try:
me = pdb.get_person(result.uid)
except steve.persondb.PersonNotFound:
@@ -344,7 +344,7 @@ async def do_open_endpoint(election):
### check authz
### should open/keep a PersonDB instance in the APP
- pdb = steve.persondb.PersonDB(DB_FNAME)
+ pdb = steve.persondb.PersonDB.open(DB_FNAME)
# Open the Election.
election.open(pdb)
diff --git a/v3/steve/persondb.py b/v3/steve/persondb.py
index a87fe17..c324346 100644
--- a/v3/steve/persondb.py
+++ b/v3/steve/persondb.py
@@ -24,8 +24,15 @@ QUERIES = THIS_DIR.parent / 'queries.yaml'
class PersonDB:
- def __init__(self, db_fname):
- self.db = asfpy.db.DB(db_fname, yaml_fname=QUERIES,
yaml_section='person')
+
+ @classmethod
+ def open(cls, db_fname):
+ return cls(asfpy.db.DB(db_fname,
+ yaml_fname=QUERIES,
+ yaml_section='person'))
+
+ def __init__(self, db):
+ self.db = db
def __getattr__(self, name):
"Proxy the cursors."
diff --git a/v3/tests/check_coverage.py b/v3/tests/check_coverage.py
index 766dbd5..d805275 100755
--- a/v3/tests/check_coverage.py
+++ b/v3/tests/check_coverage.py
@@ -54,7 +54,7 @@ def touch_every_line():
_ = e.get_metadata() # while EDITABLE
- pdb = steve.persondb.PersonDB(TESTING_DB)
+ pdb = steve.persondb.PersonDB.open(TESTING_DB)
pdb.add_person('alice', 'Alice', '[email protected]')
pdb.add_person('bob', None, '[email protected]')
pdb.add_person('carlos', 'Carlos', '[email protected]')