Working code. Need to populate

This commit is contained in:
Christopher T. Johnson
2025-02-07 17:22:24 -05:00
parent c7a9ca89f1
commit 8baee6b225
6 changed files with 222 additions and 63 deletions

66
docketModel.py Normal file
View File

@@ -0,0 +1,66 @@
import datetime
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
from PySide6.QtGui import QColor, QFont
from PySide6.QtSql import QSqlQuery
from lib.utils import query_error
class docketModel(QAbstractTableModel):
entries = []
def __init__(self, case_id:int|None = None) -> None:
super(docketModel,self).__init__()
if case_id == None:
return
query = QSqlQuery()
query.prepare("SELECT * FROM entries WHERE case_id = :cid "
"ORDER BY entry_id")
q2 = QSqlQuery()
q2.prepare("SELECT * FROM documents WHERE entry_id = :eid")
query.bindValue(":cid", case_id)
if not query.exec():
query_error(query)
while query.next():
date = datetime.date.fromtimestamp(query.value(2))
assert isinstance(date, datetime.date)
row = [
date.strftime("%B %-d, %Y"),
query.value(3)
]
self.entries.append(row)
q2.bindValue(":eid", query.value("entry_id"))
if not q2.exec():
query_error(q2)
row = []
while q2.next():
row.append(q2.value('name'))
if len(row) > 0:
self.entries.append([None, " ".join(row)])
return
def rowCount(self, parent:QModelIndex|None = None) -> int:
return len(self.entries)
def columnCount(self, parent:QModelIndex|None = None) -> int:
return 2
def data(self, index: QModelIndex, role:int):
if not index.isValid():
return ''
if role == Qt.ItemDataRole.DisplayRole:
return self.entries[index.row()][index.column()]
if role == Qt.ItemDataRole.TextAlignmentRole and index.column() == 0:
return Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
return
def headerData(self, section:int, orientation:Qt.Orientation, role:int):
if orientation == Qt.Orientation.Vertical:
return
if role == Qt.ItemDataRole.FontRole:
font = QFont()
font.setBold(True)
return font
if role != Qt.ItemDataRole.DisplayRole:
return
return ['Date', 'Proceedings and Orders'][section]

0
lib/__init__.py Normal file
View File

18
lib/utils.py Normal file
View File

@@ -0,0 +1,18 @@
from typing import NoReturn
from PySide6.QtCore import QCoreApplication
from PySide6.QtSql import QSqlQuery
translate = QCoreApplication.translate
def query_error(query: QSqlQuery) -> NoReturn:
"""Standarized query error reporter."""
print(
translate("MainWindow", "SQL Error:\n")
+ "{}\n{}\n{}:{}".format(
query.executedQuery(),
query.boundValues(),
query.lastError().type(),
query.lastError().text(),
)
)
raise Exception(translate("MainWindow", "SQL Error"))

View File

@@ -5,27 +5,16 @@ import sys
import dateparser import dateparser
import requests import requests
from typing import NoReturn from typing import NoReturn
from PySide6.QtCore import QCoreApplication, QModelIndex, Signal, Qt from PySide6.QtCore import QCoreApplication, QModelIndex, Signal, Qt, Slot
from PySide6.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel from PySide6.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel
from PySide6.QtWidgets import QAbstractItemView, QApplication, QHeaderView, QMainWindow, QStyledItemDelegate, QTableWidgetItem from PySide6.QtWidgets import QAbstractItemView, QApplication, QHeaderView, QMainWindow, QStyledItemDelegate, QTableWidgetItem
from bs4 import BeautifulSoup, Tag from bs4 import BeautifulSoup, Tag
from docketModel import docketModel
from ui.MainWindow import Ui_MainWindow from ui.MainWindow import Ui_MainWindow
from lib.utils import query_error
translate = QCoreApplication.translate translate = QCoreApplication.translate
def query_error(query: QSqlQuery) -> NoReturn:
"""Standarized query error reporter."""
print(
translate("MainWindow", "SQL Error:\n")
+ "{}\n{}\n{}:{}".format(
query.executedQuery(),
query.boundValues(),
query.lastError().type(),
query.lastError().text(),
)
)
raise Exception(translate("MainWindow", "SQL Error"))
class dateDelegate(QStyledItemDelegate): class dateDelegate(QStyledItemDelegate):
def displayText(self, value, locale) -> str: def displayText(self, value, locale) -> str:
@@ -64,40 +53,29 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.casesView.doubleClicked.connect(self.rowClicked) self.casesView.doubleClicked.connect(self.rowClicked)
self.casesView.clicked.connect(self.rowClicked) self.casesView.clicked.connect(self.rowClicked)
self.docketWidget.setColumnCount(2) self.docketView.setModel(docketModel())
self.docketWidget.setHorizontalHeaderLabels([ self.docketView.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
'Date','Proceedings and Orders', self.docketView.resizeRowsToContents()
])
self.docketWidget.resizeColumnToContents(0)
self.docketWidget.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
return
def populateDocket(self, case_id:int) -> None:
query = QSqlQuery()
query.prepare("SELECT * FROM entries WHERE case_id=:cid ORDER BY entry_id")
query.bindValue(":cid", case_id)
if not query.exec():
query_error(query)
self.docketWidget.clearContents()
row = 0
while query.next():
print(query.value(0), query.value(1), query.value(2), query.value(3))
item = QTableWidgetItem()
item.setData(Qt.ItemDataRole.DisplayRole, query.value(2))
self.docketWidget.setItem(row,0, item)
item = QTableWidgetItem()
item.setData(Qt.ItemDataRole.DisplayRole, query.value(3))
self.docketWidget.setItem(row, 1, item)
row += 1
self.docketWidget.setRowCount(row)
return return
@Slot(QModelIndex)
def rowClicked(self, index:QModelIndex) -> None: def rowClicked(self, index:QModelIndex) -> None:
if not index.isValid():
raise Exception("Bad index")
docket = index.siblingAtColumn(1).data() docket = index.siblingAtColumn(1).data()
print(docket) self.docketLabel.setText(docket)
self.show_entries.emit(index.siblingAtColumn(0).data()) self.show_entries.emit(index.siblingAtColumn(0).data())
self.populateDocket(index.siblingAtColumn(0).data()) model = docketModel(index.siblingAtColumn(0).data())
self.docketView.setModel(model)
self.docketView.resizeColumnToContents(0)
self.docketView.resizeRowsToContents()
return
@Slot()
def on_updateButton_clicked(self):
text = self.docketInput.toPlainText()
update_db(text)
self.update()
return return
SQL_CMDS = [ SQL_CMDS = [
@@ -107,6 +85,7 @@ SQL_CMDS = [
"docket_id TEXT, " "docket_id TEXT, "
"linked INTEGER, " "linked INTEGER, "
"petitioners TEXT, respondents TEXT, date INTEGER, " "petitioners TEXT, respondents TEXT, date INTEGER, "
"active INTEGER, "
"FOREIGN KEY(linked) REFERENCES cases(case_id))", "FOREIGN KEY(linked) REFERENCES cases(case_id))",
# #
"CREATE TABLE IF NOT EXISTS entries (" "CREATE TABLE IF NOT EXISTS entries ("
@@ -141,7 +120,9 @@ def schema_update(db: QSqlDatabase) -> None:
table_name = matches.group(2) table_name = matches.group(2)
create_cmd = ( create_cmd = (
matches.group(1) matches.group(1)
+ '"'
+ matches.group(2) + matches.group(2)
+ '"'
+ matches.group(3) + matches.group(3)
) )
else: else:
@@ -173,7 +154,6 @@ def schema_update(db: QSqlDatabase) -> None:
# Step 4 create new table # Step 4 create new table
new_table_name = table_name + "_new" new_table_name = table_name + "_new"
sql = matches.group(1) + new_table_name + matches.group(3) sql = matches.group(1) + new_table_name + matches.group(3)
print(sql)
if not query.exec(sql): if not query.exec(sql):
query_error(query) query_error(query)
# step 5 transfer content # step 5 transfer content
@@ -228,7 +208,7 @@ def update_proceedings(case_id: int, bs: BeautifulSoup) -> None:
if not query.next(): if not query.next():
query.prepare("INSERT INTO entries (case_id, date, text) VALUES (:cid,:date,:text)") query.prepare("INSERT INTO entries (case_id, date, text) VALUES (:cid,:date,:text)")
query.bindValue(':cid', case_id) query.bindValue(':cid', case_id)
query.bindValue(':date', date.timestamp) query.bindValue(':date', date.timestamp())
query.bindValue(':text', text) query.bindValue(':text', text)
if not query.exec(): if not query.exec():
query_error(query) query_error(query)
@@ -238,7 +218,6 @@ def update_proceedings(case_id: int, bs: BeautifulSoup) -> None:
tr = trs.pop(0) tr = trs.pop(0)
assert isinstance(tr, Tag) assert isinstance(tr, Tag)
assert isinstance(tr.contents[1], Tag) assert isinstance(tr.contents[1], Tag)
print(tr.contents[1])
for a in tr.contents[1]: for a in tr.contents[1]:
assert isinstance(a, Tag) assert isinstance(a, Tag)
url = a.attrs['href'] url = a.attrs['href']
@@ -256,7 +235,6 @@ def update_proceedings(case_id: int, bs: BeautifulSoup) -> None:
query.bindValue(":url", url) query.bindValue(":url", url)
if not query.exec(): if not query.exec():
query_error(query) query_error(query)
break
return return
def update_db(case_id) -> int: def update_db(case_id) -> int:
@@ -315,8 +293,6 @@ def update_db(case_id) -> int:
assert isinstance(tr, Tag) and isinstance(tr.contents[0], Tag) assert isinstance(tr, Tag) and isinstance(tr.contents[0], Tag)
linked = tr.contents[0].string linked = tr.contents[0].string
print(docket_id, petitioners, respondent, date, linked)
# #
# See if this case already exists. # See if this case already exists.
# #
@@ -376,8 +352,8 @@ def main() -> int:
db.setDatabaseName("scotus.db") db.setDatabaseName("scotus.db")
db.open() db.open()
schema_update(db) schema_update(db)
#update_db('24-203') update_db('24-203')
#update_db('23A1058') update_db('23A1058')
window = MainWindow() window = MainWindow()
return app.exec() return app.exec()

View File

@@ -15,15 +15,16 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon, QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter, QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform) QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QHeaderView, QMainWindow, QMenuBar, from PySide6.QtWidgets import (QApplication, QFrame, QHBoxLayout, QHeaderView,
QSizePolicy, QStatusBar, QTableView, QTableWidget, QLabel, QMainWindow, QMenuBar, QPlainTextEdit,
QTableWidgetItem, QVBoxLayout, QWidget) QPushButton, QSizePolicy, QStatusBar, QTableView,
QVBoxLayout, QWidget)
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
if not MainWindow.objectName(): if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow") MainWindow.setObjectName(u"MainWindow")
MainWindow.resize(800, 600) MainWindow.resize(929, 710)
self.centralwidget = QWidget(MainWindow) self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget") self.centralwidget.setObjectName(u"centralwidget")
self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout = QVBoxLayout(self.centralwidget)
@@ -33,15 +34,55 @@ class Ui_MainWindow(object):
self.verticalLayout.addWidget(self.casesView) self.verticalLayout.addWidget(self.casesView)
self.docketWidget = QTableWidget(self.centralwidget) self.docketLabel = QLabel(self.centralwidget)
self.docketWidget.setObjectName(u"docketWidget") self.docketLabel.setObjectName(u"docketLabel")
self.verticalLayout.addWidget(self.docketWidget) self.verticalLayout.addWidget(self.docketLabel)
self.docketView = QTableView(self.centralwidget)
self.docketView.setObjectName(u"docketView")
self.verticalLayout.addWidget(self.docketView)
self.frame = QFrame(self.centralwidget)
self.frame.setObjectName(u"frame")
sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth())
self.frame.setSizePolicy(sizePolicy)
self.frame.setFrameShape(QFrame.Shape.StyledPanel)
self.frame.setFrameShadow(QFrame.Shadow.Raised)
self.horizontalLayout = QHBoxLayout(self.frame)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.docketInput = QPlainTextEdit(self.frame)
self.docketInput.setObjectName(u"docketInput")
sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.docketInput.sizePolicy().hasHeightForWidth())
self.docketInput.setSizePolicy(sizePolicy1)
self.docketInput.setMaximumSize(QSize(16777215, 27))
self.horizontalLayout.addWidget(self.docketInput)
self.updateButton = QPushButton(self.frame)
self.updateButton.setObjectName(u"updateButton")
self.horizontalLayout.addWidget(self.updateButton)
self.searchButton = QPushButton(self.frame)
self.searchButton.setObjectName(u"searchButton")
self.horizontalLayout.addWidget(self.searchButton)
self.verticalLayout.addWidget(self.frame)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(MainWindow) self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar") self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 800, 24)) self.menubar.setGeometry(QRect(0, 0, 929, 24))
MainWindow.setMenuBar(self.menubar) MainWindow.setMenuBar(self.menubar)
self.statusbar = QStatusBar(MainWindow) self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar") self.statusbar.setObjectName(u"statusbar")
@@ -54,5 +95,8 @@ class Ui_MainWindow(object):
def retranslateUi(self, MainWindow): def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
self.docketLabel.setText(QCoreApplication.translate("MainWindow", u"TextLabel", None))
self.updateButton.setText(QCoreApplication.translate("MainWindow", u"Update Docket", None))
self.searchButton.setText(QCoreApplication.translate("MainWindow", u"Search", None))
# retranslateUi # retranslateUi

View File

@@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>929</width>
<height>600</height> <height>710</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@@ -19,7 +19,62 @@
<widget class="QTableView" name="casesView"/> <widget class="QTableView" name="casesView"/>
</item> </item>
<item> <item>
<widget class="QTableWidget" name="docketWidget"/> <widget class="QLabel" name="docketLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="docketView"/>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0">
<item>
<widget class="QPlainTextEdit" name="docketInput">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>27</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="updateButton">
<property name="text">
<string>Update Docket</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="searchButton">
<property name="text">
<string>Search</string>
</property>
</widget>
</item>
</layout>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@@ -28,7 +83,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>929</width>
<height>24</height> <height>24</height>
</rect> </rect>
</property> </property>