Library reference¶
Generated from the source. Each docstring names the Chadwick C function it translates.
Parser, games and files (Chadwick's cwlib)¶
chadwickpy.parse
¶
Port of Chadwick's play-text parser (src/cwlib/parse.c).
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball
Bureau, licensed GPL-2.0-or-later. This module is a Python translation of its
parser, so it is a derivative work and keeps that notice. Function names map
one-to-one onto the C functions (cw_parse_x -> _x) so the two can be
read side by side. Where the C code has quirks (a shared token buffer, return
value 0 meaning both "batter out" and "invalid", fixed-size arrays) the quirk is
kept on purpose: the goal is byte-identical cwevent output.
Ev
¶
Bases: IntEnum
CWEventType. Codes 0-24 are the Retrosheet event codes.
EventData
dataclass
¶
CWEventData: everything the play text alone says about the play.
is_batter(e)
¶
cw_event_is_batter
is_official_ab(e)
¶
cw_event_is_official_ab
outs_on_play(e)
¶
cw_event_outs_on_play
parse_event(text)
¶
cw_parse_event: parse play text into :class:EventData.
Returns the (possibly half-filled, as in C) data and whether it parsed.
rbi_on_play(e)
¶
cw_event_rbi_on_play
runner_put_out(e, base)
¶
cw_event_runner_put_out
runs_on_play(e)
¶
cw_event_runs_on_play
chadwickpy.game
¶
Port of Chadwick's game container (src/cwlib/game.c, reading side).
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball
Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps
that notice. It follows cw_game_read: events carry the substitutions,
comments and adjustment records (badj, padj, ladj, radj,
presadj) that appear after them in the file.
Appearance
dataclass
¶
CWAppearance: a start or sub record.
Comment
dataclass
¶
CWComment: a com record, with the ej, and umpchange, fields split out.
Event
dataclass
¶
CWEvent: one play record plus what trails it.
Game
dataclass
¶
CWGame
comment_append(text)
¶
cw_game_comment_append: to the last event, or the game before any event
data_append(data)
¶
cw_game_data_append
data_set_er(player_id, er)
¶
cw_game_data_set_er: set the earned runs of a pitcher's data,er record
evdata_append(data)
¶
cw_game_evdata_append
event_append(inning, batting_team, batter, count, pitches, event_text)
¶
cw_game_event_append
info_append(label, data)
¶
cw_game_info_append
info_lookup(label)
¶
cw_game_info_lookup: the last info record with this label.
info_set(label, data)
¶
cw_game_info_set: replace the first record with this label, else append.
(info_lookup reads the last one; the C is inconsistent and so is this.)
line_append(data)
¶
cw_game_line_append
replace_player(key_old, key_new)
¶
cw_game_replace_player: every use of the id, in the order the C visits them
set_version(version)
¶
cw_game_set_version
starter_append(player_id, name, team, slot, pos)
¶
cw_game_starter_append
starter_by_position(team, pos)
¶
cw_game_starter_find_by_position
starter_find(team, slot)
¶
cw_game_starter_find
stat_append(data)
¶
cw_game_stat_append
substitute_append(player_id, name, team, slot, pos)
¶
cw_game_substitute_append: to the last event
truncate(event)
¶
cw_game_truncate: drop event and every event after it
count_pitches(pitches, criterion)
¶
cw_pitch_count_pitches
event_comment_append(event, text)
¶
cw_event_comment_append: a comment on an event, with no ej,/umpchange, parsing
pitch_ball_thrown(c)
¶
cw_pitch_ball_thrown
pitch_strike_thrown(c)
¶
cw_pitch_strike_thrown
read_game(file)
¶
cw_game_read: the next game, or None at the end of the file or on a bad header.
read_games(data)
¶
Every game cw_game_read returns from the file contents, as cwevent reads them.
Reading stops, as in Chadwick, when cw_game_read returns NULL. If bytes
are left unread then (a file not starting with an id record, say) a warning
is logged, because Chadwick stops there without a message.
chadwickpy.gameiter
¶
Port of Chadwick's game iterator (src/cwlib/gameiter.c).
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball
Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps
that notice. Names map onto the C functions (cw_gamestate_x -> State.x
or a module function) so the two can be read side by side.
Unset C pointers (NULL strings) are None here.
Appearance
dataclass
¶
CWAppearance: a start or sub record.
GameIter
¶
Runner
dataclass
¶
One entry of CWGameState.runners; base 0 is the batter-runner.
Slot
dataclass
¶
One lineup entry (CWLineupEntry).
State
dataclass
¶
CWGameState
base_occupied(base)
¶
cw_gamestate_base_occupied
change_sides(event)
¶
cw_gamestate_change_sides
charged_batter_hand(batter, d, off_roster, def_roster)
¶
cw_gamestate_charged_batter_hand
copy()
¶
cw_gamestate_copy
lineup_slot(team, player_id)
¶
cw_gamestate_lineup_slot: search from slot 9 down to prefer batting-order slots.
player_position(team, player_id)
¶
cw_gamestate_player_position
runner_position(team, player_id)
¶
cw_gamestate_runner_position: the position associated with a runner, without the
batted-around adjustment used for the batter's PH/PR statistics.
substitute(batter, count, player_id, name, team, slot, pos)
¶
cw_gamestate_substitute
update(batter, d)
¶
cw_gamestate_update
chadwickpy.roster
¶
Port of Chadwick's src/cwlib/roster.c and league.c (reading side).
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps that notice.
A TEAMyyyy file lists the teams of a season (league.c); each team has a
<team><year>.ROS roster file (roster.c) giving the players' batting and
throwing hands, which cwevent prints for players without a badj/padj.
League
dataclass
¶
Player
dataclass
¶
Roster
dataclass
¶
CWRoster
player_append(player)
¶
cw_roster_player_append
player_count()
¶
cw_roster_player_count
player_find(player_id)
¶
cw_roster_player_find
player_insert(player)
¶
cw_roster_player_insert: before the first player whose id is not smaller (strcmp)
read(data)
¶
cw_roster_read: append the players of a .ROS file's contents
set_city(city)
¶
cw_roster_set_city
set_league(league)
¶
cw_roster_set_league
set_nickname(nickname)
¶
cw_roster_set_nickname
roster_batting_hand(roster, player_id)
¶
cw_roster_batting_hand: ? when the roster or the player is unknown
roster_throwing_hand(roster, player_id)
¶
cw_roster_throwing_hand
chadwickpy.box
¶
Port of Chadwick's boxscore builder (src/cwlib/box.c and box.h).
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball
Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps
that notice. Names map onto the C functions (cw_box_x -> x) so the two
can be read side by side.
Data layout follows box.h. Players and pitchers stay doubly linked
(slots[slot][team] and pitchers[team] point at the current entry; walk
prev for earlier ones), because Chadwick's tools walk them that way. The
notable-event lists (b2_list ...) are plain Python lists in file order
instead of linked lists. Unset C pointers are None.
Where the C ends the program (exit(1)) or dereferences NULL, this port
raises ValueError; messages Chadwick prints to stderr go to logging.
BoxBatting
dataclass
¶
CWBoxBatting
BoxEvent
dataclass
¶
CWBoxEvent: a notable event (extra-base hit, wild pitch, ...).
BoxFielding
dataclass
¶
CWBoxFielding
BoxPitcher
¶
CWBoxPitcher: a pitcher's entry in the boxscore.
__init__(player_id, name)
¶
cw_box_pitcher_create
BoxPitching
dataclass
¶
CWBoxPitching
BoxPlayer
¶
Boxscore
¶
CWBoxscore
add_event(events, inning, half, *players)
¶
cw_box_add_event: players are the count strings of its variable arguments.
add_substitute(box, gi)
¶
cw_box_add_substitute: add a substitute into a slot
batter_stats(box, gi)
¶
cw_box_batter_stats: update batter/pitcher stats with the current play
box_create(game)
¶
cw_box_create: compile a boxscore for game
enter_starters(box, game)
¶
cw_box_enter_starters: initialize slots with starting players
fielder_stats(box, gi)
¶
cw_box_fielder_stats: update fielding stats with the current play
find_current_player(box, player_id, batting_only)
¶
cw_box_find_current_player
Unlike find_player this only searches, and returns, entries from among players currently
in the game. That matters when building the boxscore, in the case of an illegal (or
sanctioned but unorthodox) re-entry of a player in a different lineup slot.
find_pitcher(box, player_id)
¶
cw_box_find_pitcher (strcmp against NULL is undefined; it never matches here)
find_player(box, player_id, batter)
¶
cw_box_find_player
If batter, search only batting entries; this implements the 'Ohtani rule' for DHes, in
which a player who DHes for himself has two identities within the game, one in the batting
order and one as the DHed-for pitcher.
get_fielding(player, pos)
¶
player->fielding[pos] for a position taken from the data.
The C does not check pos. Retrosheet writes a missing or unreadable position as -1, and
fielding[-1] is then the 8 bytes just before the array: positions[38] and
positions[39] of the same struct. The C survives and never reads those back as positions,
so the port keeps such entries in stray_fielding. (Positions 10 and up would overwrite the
prev/next links, which the port cannot mimic, so they raise.)
get_starter(box, team, slot)
¶
cw_box_get_starter: the starter for team in batting order position slot
get_starting_pitcher(box, team)
¶
cw_box_get_starting_pitcher
iterate_game(box, game)
¶
cw_box_iterate_game: iterate through the game, building the boxscore
pitch_stats(box, gi)
¶
cw_box_pitch_stats: update pitch stats with the current event
Called even for NP events, as pitches may occur prior to a substitution. Only counts pitches following the last period in the pitch string.
process_boxscore_file(box, game)
¶
cw_box_process_boxscore_file
In these files, all the statistical information is stored in extended stat records.
put_fielding(player, pos, value)
¶
player->fielding[pos] = value; see :func:get_fielding.
runner_stats(box, gi)
¶
cw_box_runner_stats: update baserunning stats with the current play
set_position_slot(player, index, value)
¶
player->positions[index] = value for an index taken from the data (seq - 1).
Retrosheet writes an unreadable sequence number as -1, so index is -2. In the C struct the
four ints in front of positions are ph_inn, pr_inn, num_positions and
start_position, so positions[-1] is start_position, [-2] is num_positions,
[-3] is pr_inn and [-4] is ph_inn: the write lands on that field.
chadwickpy.book
¶
Port of Chadwick's src/cwlib/book.c (cw_scorebook_read) and cw_file_find_first_game.
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps that notice.
Scorebook
dataclass
¶
CWScorebook: the leading comments of an event file and its games
append_game(game)
¶
cw_scorebook_append_game: False (nothing done) for NULL
insert_game(game)
¶
cw_scorebook_insert_game: before the first game not earlier by date, then number
iterate(f=None)
¶
cw_scorebook_iterate / _iterator_next: games for which f is true
read(data)
¶
cw_scorebook_read: the number of games read, or -1 for an empty file
remove_game(game_id)
¶
cw_scorebook_remove_game: the first game with this id, or None
find_first_game(file)
¶
cw_file_find_first_game: rewind, then stop at the first line that begins id
scorebook_read(data)
¶
cw_scorebook_read: every game of an event file, or None where C returns -1.
None is the "could not open file" case of cwtools_process_scorebook: an
empty file.
chadwickpy.file
¶
Port of the reading helpers in Chadwick's src/cwlib/file.c.
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps that notice.
Chadwick 0.11.0 reads event, roster and team files with a record reader
(CWRecordReader) and splits each line with a tokenizer (CWTokenizer). Both
are reproduced here, including the quirks that decide what a file means: a line may
be any length, every is dropped wherever it stands (so CRLF and CR-only
breaks inside a line vanish), a last line with no trailing newline is read like any
other, and text is handled as C strings, so a NUL byte ends a line. Text is held as
latin-1 so that one byte is one character, as in C.
CFile
¶
The part of a C FILE * that the record reader uses on a file.
getline()
¶
cw_record_reader_next: the next line without its and without any .
Returns ``None`` at the end of the file: ``cw_getline`` reports -1 when the end was
reached with nothing kept, which includes a final stretch of nothing but ``
. The
end-of-file flag is set when the read ran into the end of the data, asfeof`` is.
getpos()
¶
fgetpos
setpos(pos)
¶
fsetpos: also clears the end-of-file flag
ReportedError
¶
Bases: ValueError
The C prints this message itself (on stderr) and calls exit(1).
The port logs the message and raises this, so the command line ends with status 1 without printing the message a second time.
Tokenizer
¶
CWTokenizer: split a line on commas, honouring a quote at the start of a field.
tok(line) is cw_tokenizer_init followed by the first cw_tokenizer_next;
tok(None) is a further cw_tokenizer_next. The C tokenizer writes a NUL over each
comma or closing quote that ends a field, so the line it was given afterwards reads as
the text up to the first such NUL; :meth:line_text gives that text, which the
"invalid record" warning prints.
cw_atoi(text, msg=None)
¶
cw_atoi: strtol with validity checking; -1 (Retrosheet's null) when invalid.
Like strtol, it skips leading white space, accepts a sign, and stops at
the first non-digit, so trailing text is ignored. Only a string with no
digits at all, or a value outside int, is invalid.
scan_int(text, pos=0)
¶
One %d conversion of sscanf at pos: (value, position after it), or None
when no integer is there (sscanf then stops and leaves its outputs unset)
The tools (Chadwick's cwtools)¶
chadwickpy.tools.events
¶
Port of Chadwick's cwevent field logic (src/cwtools/cwevent.c).
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball
Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps
that notice. One function per cwevent field, in the same order, producing
the text cwevent -q (quoted/ascii mode) prints for that field. Rows are
dicts keyed by the cwevent column names.
0.11.0 prints every string field through cw_buffer_emit_string, which turns a NULL
into "" (0.10 passed it to %s, which glibc prints as "(null)"); None renders "" here.
event_lines(data, league=None, game_id='', first_date='0101', last_date='1231', ascii_=True, fields=DEFAULT_FIELDS, ext_fields=())
¶
Lines for the selected games of an event file, as cwevent prints them.
event_rows(data, league=None, game_id='', first_date='0101', last_date='1231')
¶
Rows for the selected games of an event file, as cwevent -q -f 0-96 -x 0-66 does.
league holds the rosters read from the team file; without it every hand not given by
a badj/padj record is ?.
game_lines(game, visitors=None, home=None, ascii_=True, fields=DEFAULT_FIELDS, ext_fields=())
¶
cwevent_process_game: one output line per non-NP event of the game
game_rows(game, visitors=None, home=None)
¶
cwevent_process_game: one row per non-NP event of the game.
header_line(fields, ext_fields)
¶
cwevent_initialize with -n: the quoted column names (ascii format only)
chadwickpy.tools.tools
¶
Port of the parts of Chadwick's src/cwtools/cwtools.c that every tool shares.
Chadwick is Copyright (c) 2002-2026 Dr T L Turocy and the Chadwick Baseball Bureau, licensed GPL-2.0-or-later; this module is a derivative of it and keeps that notice.
cwtools.c is the driver of cwevent, cwgame and the other tools: it reads the
team file and rosters, reads each event file as a scorebook, picks the games the options
select, and hands each game with its two rosters to the tool. Reading files from disk
and the command line are left to the caller; these functions take bytes.
cut_at_nul(row)
¶
printf("%s") of an output row stops at the first NUL byte that a field wrote.
date_digits(date, indices=(0, 1, 2, 3, 5, 6, 8, 9))
¶
The eight characters cwgame_date and cwdaily_date print: date[0..3], [5], [6], [8],
[9] (YYYYMMDD for a YYYY/MM/DD date), read with %c and no length check.
For a date shorter than 10 characters the C reads the string's terminating NUL, which is in
bounds, as one of those characters. printf("%s") then stops at it, so the text ends there
and the rest of the output row is lost. The result holds that NUL (the caller cuts the row at
it). Where the C would read beyond the terminator the bytes are leftovers, so that raises.
indices are the characters read, in print order (cwgame has several date formats).
game_in_range(game, first, last)
¶
cwtools_game_in_range: is the game's month and day between first and last
iterate_games(data, league=None, game_id='', first='0101', last='1231')
¶
cwtools_process_scorebook + cwtools_iterate_games: the selected games of one event
file with the visiting and home rosters (None where the team is not in the team file).
An empty file yields nothing (Chadwick prints "could not open file").
read_rosters(team_file, year, roster_file)
¶
cwtools_read_rosters: the team file, then each team's <team><year>.ROS if present.
roster_file is given a file name and returns its contents, or None where Chadwick's
fopen fails; a missing roster file is silently skipped, as in Chadwick.
select_game(game, game_id='', first='0101', last='1231')
¶
cwtools_select_game