Skip to content

Commit 1db7f66

Browse files
authored
Merge pull request #116 from JeffersonLab/romanov_web_refactor
Web site refactoring
2 parents a51442e + 050633f commit 1db7f66

File tree

182 files changed

+633
-602
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

182 files changed

+633
-602
lines changed

python/rcdb/rcdb_cli/app.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from .ls import ls as ls_cmd
1212
from .repair import repair as repair_grp
1313
from .db import db as db_grp
14+
from .rp import rp as rp_grp
1415

1516

1617
pass_rcdb_context = click.make_pass_decorator(RcdbApplicationContext)
@@ -67,6 +68,10 @@ def rcdb_cli(ctx, user_config, connection, config, verbose):
6768
# noinspection PyTypeChecker
6869
rcdb_cli.add_command(db_grp)
6970

71+
# Add 'rp' group of commands
72+
# noinspection PyTypeChecker
73+
rcdb_cli.add_command(rp_grp)
74+
7075

7176

7277
@rcdb_cli.command()

python/rcdb/rcdb_cli/ls.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
def ls(context, search, is_long):
1212
"""Lists conditions"""
1313

14-
1514
db = context.db
1615
assert isinstance(db, RCDBProvider)
1716
cnd_types = db.get_condition_types_by_name()

python/rcdb/rcdb_cli/rp.py

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
# rp.py
2+
import click
3+
import sqlalchemy
4+
from sqlalchemy import select
5+
from sqlalchemy.exc import OperationalError
6+
7+
import rcdb
8+
from rcdb import RCDBProvider
9+
from rcdb.model import RunPeriod
10+
from rcdb.rcdb_cli.context import pass_rcdb_context
11+
12+
@click.group(invoke_without_command=True)
13+
@click.pass_context
14+
def rp(context):
15+
"""
16+
Run Periods management commands.
17+
18+
If invoked without a subcommand, this command lists all run periods.
19+
"""
20+
21+
connection_str = context.obj.connection_str
22+
if not connection_str:
23+
print("ERROR connection string is missing.")
24+
exit(1)
25+
26+
if context.invoked_subcommand is not None:
27+
return
28+
29+
provider = context.obj.db
30+
assert isinstance(provider, RCDBProvider)
31+
32+
session = provider.session
33+
run_periods = session.query(RunPeriod).order_by(RunPeriod.id.asc()).all()
34+
if not run_periods:
35+
print("No run periods found.")
36+
return
37+
38+
print_run_periods(run_periods)
39+
40+
41+
@rp.command()
42+
@click.option('--name', required=True, help="Name of the run period, e.g. RunPeriod-2025-01.")
43+
@click.option('--description', default='', help="Description of the run period.")
44+
@click.option('--run-min', 'run_min', required=True, type=int, help="Minimum run number in the period.")
45+
@click.option('--run-max', 'run_max', required=True, type=int, help="Maximum run number in the period.")
46+
@click.option('--start-date', default=None, help="Start date in YYYY-MM-DD format.")
47+
@click.option('--end-date', default=None, help="End date in YYYY-MM-DD format.")
48+
@pass_rcdb_context
49+
def add(context, name, description, run_min, run_max, start_date, end_date):
50+
"""
51+
Adds a new run period.
52+
"""
53+
connection_str = context.connection_str
54+
if not connection_str:
55+
print("ERROR: No connection string provided.")
56+
exit(1)
57+
58+
provider = RCDBProvider()
59+
provider.connect(connection_str, check_version=False)
60+
session = provider.session
61+
62+
# Convert date strings to Date objects if provided
63+
# You may want to handle exceptions for invalid formats
64+
s_date = None
65+
e_date = None
66+
67+
if start_date:
68+
try:
69+
s_date = sqlalchemy.sql.func.DATE(start_date) # or use datetime.strptime
70+
except ValueError:
71+
print(f"ERROR: Invalid start-date format '{start_date}'. Should be YYYY-MM-DD.")
72+
exit(1)
73+
74+
if end_date:
75+
try:
76+
e_date = sqlalchemy.sql.func.DATE(end_date)
77+
except ValueError:
78+
print(f"ERROR: Invalid end-date format '{end_date}'. Should be YYYY-MM-DD.")
79+
exit(1)
80+
81+
# Create and insert the new RunPeriod
82+
new_period = RunPeriod(name=name,
83+
description=description,
84+
run_min=run_min,
85+
run_max=run_max,
86+
start_date=start_date,
87+
end_date=end_date)
88+
session.add(new_period)
89+
session.commit()
90+
91+
print(f"Added new run period: {new_period}")
92+
93+
@rp.command()
94+
@click.argument('period_id', type=int)
95+
@click.option('--yes', is_flag=True, help="Skip prompt confirmation and remove directly.")
96+
@pass_rcdb_context
97+
def rm(context, period_id, yes):
98+
"""
99+
Removes a run period by ID.
100+
"""
101+
connection_str = context.connection_str
102+
if not connection_str:
103+
print("ERROR: No connection string provided.")
104+
exit(1)
105+
106+
provider = RCDBProvider()
107+
provider.connect(connection_str, check_version=False)
108+
session = provider.session
109+
110+
rp_item = session.query(RunPeriod).filter(RunPeriod.id == period_id).one_or_none()
111+
if not rp_item:
112+
print(f"ERROR: Run period with ID={period_id} was not found.")
113+
exit(1)
114+
115+
# If user didn't supply --yes, prompt for confirmation
116+
if not yes:
117+
if not click.confirm(f"Do you really want to remove run period ID={period_id} ({rp_item.name})?"):
118+
print("Aborted.")
119+
return
120+
121+
session.delete(rp_item)
122+
session.commit()
123+
print(f"Removed run period ID={period_id} ({rp_item.name}).")
124+
125+
@rp.command()
126+
@click.argument('period_id', type=int)
127+
@click.option('--name', default=None, help="New name of the run period.")
128+
@click.option('--description', default=None, help="New description of the run period.")
129+
@click.option('--run-min', 'run_min', type=int, default=None, help="New minimum run number.")
130+
@click.option('--run-max', 'run_max', type=int, default=None, help="New maximum run number.")
131+
@click.option('--start-date', default=None, help="New start date in YYYY-MM-DD format.")
132+
@click.option('--end-date', default=None, help="New end date in YYYY-MM-DD format.")
133+
@pass_rcdb_context
134+
def update(context, period_id, name, description, run_min, run_max, start_date, end_date):
135+
"""
136+
Updates an existing run period by ID.
137+
"""
138+
connection_str = context.connection_str
139+
if not connection_str:
140+
print("ERROR: No connection string provided.")
141+
exit(1)
142+
143+
provider = RCDBProvider()
144+
provider.connect(connection_str, check_version=False)
145+
session = provider.session
146+
147+
rp_item = session.query(RunPeriod).filter(RunPeriod.id == period_id).one_or_none()
148+
if not rp_item:
149+
print(f"ERROR: Run period with ID={period_id} was not found.")
150+
exit(1)
151+
152+
if name is not None:
153+
rp_item.name = name
154+
if description is not None:
155+
rp_item.description = description
156+
if run_min is not None:
157+
rp_item.run_min = run_min
158+
if run_max is not None:
159+
rp_item.run_max = run_max
160+
if start_date is not None:
161+
# You may want to parse and validate the date string similarly as in add()
162+
rp_item.start_date = start_date
163+
if end_date is not None:
164+
rp_item.end_date = end_date
165+
166+
session.commit()
167+
print(f"Updated run period ID={period_id}: {rp_item}")
168+
169+
def print_run_periods(run_periods):
170+
# 1) Gather data strings and compute column widths
171+
# ------------------------------------------------
172+
# - We'll measure lengths of the run period's name
173+
# - We'll measure lengths of the "[run_min-run_max]" string
174+
175+
# Build a list of rows so we only format once
176+
rows = []
177+
for rp_item in run_periods:
178+
id_str = str(rp_item.id)
179+
name_str = rp_item.name
180+
runs_str = f"[{rp_item.run_min}-{rp_item.run_max}]"
181+
# Dates are fixed width, 23 chars, like "2025-01-30 - 2026-07-30"
182+
# We'll store the final string but no need to measure it for alignment
183+
if rp_item.start_date and rp_item.end_date:
184+
dates_str = f"{rp_item.start_date} - {rp_item.end_date}"
185+
else:
186+
# Handle possible missing dates
187+
start_str = str(rp_item.start_date) if rp_item.start_date else "None"
188+
end_str = str(rp_item.end_date) if rp_item.end_date else "None"
189+
dates_str = f"{start_str} - {end_str}"
190+
191+
description_str = rp_item.description if rp_item.description else ""
192+
193+
rows.append((id_str, name_str, runs_str, dates_str, description_str))
194+
195+
# Determine max width for NAME and RUNS
196+
# (ID is small, and DATES is fixed)
197+
max_name_width = max(len(row[1]) for row in rows) if rows else 10
198+
max_runs_width = max(len(row[2]) for row in rows) if rows else 10
199+
200+
# We'll define a fixed width for DATES as 23
201+
# (YYYY-MM-DD - YYYY-MM-DD) => 10 + 3 + 10 = 23
202+
date_width = 23
203+
204+
# 2) Print the table header
205+
# -------------------------
206+
header_id = "ID"
207+
header_name = "NAME"
208+
header_runs = "RUNS"
209+
header_dates = "DATES"
210+
header_description = "DESCRIPTION"
211+
212+
# Construct the format string
213+
# e.g. ID (left), NAME (left, max_name_width), RUNS (left, max_runs_width),
214+
# DATES (left, date_width), DESCRIPTION at the end (no fixed width).
215+
row_format = (
216+
f"{{:<3}} " # ID has a small width, left aligned
217+
f"{{:<{max_name_width}}} "
218+
f"{{:<{max_runs_width}}} "
219+
f"{{:<{date_width}}} "
220+
f"{{}}" # Description no fixed width
221+
)
222+
223+
# Print header row
224+
print(row_format.format(
225+
header_id,
226+
header_name,
227+
header_runs,
228+
header_dates,
229+
header_description
230+
))
231+
232+
# Print a separator row
233+
print(row_format.format(
234+
"-" * len(header_id),
235+
"-" * max_name_width,
236+
"-" * max_runs_width,
237+
"-" * date_width,
238+
"-" * len(header_description)
239+
))
240+
241+
# 3) Print all rows
242+
# -----------------
243+
for (id_str, name_str, runs_str, dates_str, description_str) in rows:
244+
print(row_format.format(
245+
id_str,
246+
name_str,
247+
runs_str,
248+
dates_str,
249+
description_str
250+
))

python/rcdb/rcdb_cli/run.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import click
2+
3+
from rcdb.provider import RCDBProvider
4+
from .context import pass_rcdb_context
5+
6+
7+
@click.command()
8+
@click.argument('run_index', required=False)
9+
@click.argument('condition', required=False)
10+
@pass_rcdb_context
11+
def ls(context, run_index, condition):
12+
"""Lists conditions"""
13+
14+
db = context.db
15+
assert isinstance(db, RCDBProvider)
16+
17+
18+
19+
def show_value(db, run_number, name):
20+
"""
21+
Shows condition value for run
22+
23+
:param db: RCDBProvider to database
24+
:type db: RCDBProvider
25+
:param run_number: The run number
26+
:param name: Condition type name
27+
:return:
28+
"""
29+
30+
run = db.get_run(run_number)
31+
if not run:
32+
print("Run number '{}' is not found in DB".format(run_number))
33+
exit(1)
34+
35+
ct = db.get_condition_type(name)
36+
37+
result = db.get_condition(run, ct)
38+
if not result:
39+
return
40+
41+
condition = result
42+
print(condition.value)
43+
44+
45+
def show_run_conditions(db, run_number):
46+
"""
47+
48+
:param db: RCDBProvider to database
49+
:type db: RCDBProvider
50+
:param run_number: The run number
51+
:return:
52+
"""
53+
54+
run = db.get_run(run_number)
55+
if not run:
56+
print("Run number {} is not found in DB".format(run_number))
57+
exit(1)
58+
59+
conditions = db.session.query(Condition).join(Run).join(ConditionType) \
60+
.order_by(asc(ConditionType.name)) \
61+
.filter(Run.number == run_number) \
62+
.all()
63+
64+
for condition in conditions:
65+
condition_type = condition.type
66+
67+
if condition_type.value_type in [ConditionType.INT_FIELD,
68+
ConditionType.BOOL_FIELD,
69+
ConditionType.FLOAT_FIELD]:
70+
print("{} = {}".format(condition_type.name, condition.value))
71+
elif condition_type.value_type == ConditionType.STRING_FIELD:
72+
print("{} = '{}'".format(condition_type.name, condition.value))
73+
else:
74+
# it is something big...
75+
value = str(condition.value).replace('\n', "")[:50]
76+
print("{} = ({}){}...".format(condition_type.name, condition_type.value_type, value))
File renamed without changes.

0 commit comments

Comments
 (0)