Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Add CLI script for resume text/link extraction by michaelmwu · Pull Request #185 · 508-dev/508-workflows · GitHub
Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add CLI script for resume text/link extraction by michaelmwu · Pull Request #185 · 508-dev/508-workflows · GitHub
Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add CLI script for resume text/link extraction by michaelmwu · Pull Request #185 · 508-dev/508-workflows · GitHub
Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Add CLI script for resume text/link extraction by michaelmwu · Pull Request #185 · 508-dev/508-workflows · GitHub
Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add CLI script for resume text/link extraction by michaelmwu · Pull Request #185 · 508-dev/508-workflows · GitHub
Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Add CLI script for resume text/link extraction by michaelmwu · Pull Request #185 · 508-dev/508-workflows · GitHub
Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Add CLI script for resume text/link extraction by michaelmwu · Pull Request #185 · 508-dev/508-workflows · GitHub
Skip to content

Add CLI script for resume text/link extraction - #185

Merged
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link
Mar 9, 2026
Merged

Add CLI script for resume text/link extraction#185
michaelmwu merged 4 commits into
mainfrom
michaelmwu/resume-text-link

Conversation

@michaelmwu

@michaelmwumichaelmwu commented Mar 9, 2026

Copy link
Copy Markdown
Member

Description

Added scripts/resume_text_extractor.py: a command-line utility that reads resume files, extracts text via shared helpers, and prints candidate links.
The script uses a public helper wrapper in the CLI module for normalized link extraction with confidence scores to avoid calling private resume extractor internals directly.
The tool supports JSON and plain text output, optional full-text or truncated output, and multiple input files per run.

Related Issue

None.

How Has This Been Tested?

Reviewed the diff against origin/main and verified the script formatting and checks pass during commit-time validation.

Summary by CodeRabbit

  • New Features
    • Added a command-line tool for extracting text and discovering links from resume files.
    • Added flexible output options: human-readable format and JSON with configurable text truncation limits.

CopilotAI review requested due to automatic review settings March 9, 2026 07:09
@coderabbitai

coderabbitaiBot commented Mar 9, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds a new CLI utility scripts/resume_text_extractor.py that reads resume files, extracts text via extract_document_text, finds website link candidates via ResumeProfileExtractor._extract_website_link_candidates, and prints results in human-readable or JSON form with configurable text truncation and error handling.

Changes

Cohort / File(s)Summary
Resume Text Extractor CLI
scripts/resume_text_extractor.py
New command-line tool introducing FileResult dataclass, argument parser (--text-max, --json, FILEs), text extraction orchestration, link-candidate extraction, per-file processing, pretty and JSON output formats, and robust error handling.

Sequence Diagram

sequenceDiagram
participant User as User
participant CLI as CLI Parser
participant Processor as File Processor
participant DocExt as extract_document_text
participant LinkExt as ResumeProfileExtractor
participant Formatter as Output Formatter
User->>CLI: Run script with files & options
CLI->>CLI: Parse args (--text-max, --json, files)
CLI->>Processor: Process each file path
loop per file
Processor->>DocExt: extract_document_text(file)
DocExt-->>Processor: extracted text
Processor->>LinkExt: _extract_website_link_candidates(text)
LinkExt-->>Processor: link candidates + scores
Processor-->>CLI: FileResult(path, text_len, text, links)
end
CLI->>Formatter: Choose pretty or JSON output
Formatter-->>User: Display formatted results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hop through files both near and far,
I pull the text and spot each URL star,
JSON or pretty — output on cue,
Links lined up with confidence true,
Hooray, resumes revealed, one-two-three!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately and concisely summarizes the main change: adding a CLI script for resume text and link extraction, which matches the primary purpose of the new scripts/resume_text_extractor.py file.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch michaelmwu/resume-text-link

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a developer-facing CLI utility to quickly run the shared resume document text extractor and surface URL candidates produced by the current resume link-extraction heuristics.

Changes:

  • Introduces scripts/resume_text_link_test.py CLI to extract text from one or more resume files.
  • Prints extracted website link candidates (with confidence scores) in either pretty text or JSON.
  • Adds optional extracted-text truncation control via --text-max.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
except Exception as exc: # pragma: no cover - runtime diagnostic path
print(f"error: failed to process {path}: {exc}")
exit_code = 1

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is printed to stdout; when running with --json it will break JSON parsing. Please write errors to stderr (e.g., print(..., file=sys.stderr)) so the JSON output on stdout remains clean.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
if not path.is_file():
print(f"error: missing file: {path}")
exit_code = 1
continue

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In --json mode this print() writes error text to stdout, which will corrupt the JSON output and make it non-machine-readable. Please send error messages to stderr (or use logging configured to stderr) so stdout remains valid JSON when --json is set.

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_link_test.py (2)

107-117: Print errors to stderr instead of stdout.

Error messages (lines 110, 116) are printed to stdout, which can contaminate the JSON output when piped. For CLI tools, errors should go to stderr.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 107 - 117, The error prints in
the loop over args.files (using path.is_file checks and the exception handler
around _process_file(path)) write to stdout and should be written to stderr;
change the two print calls that report missing file and failed processing to
write to stderr (e.g., print(..., file=sys.stderr) or sys.stderr.write) and
ensure sys is imported at the top of the script so stderr is available.

58-67: Coupling to internal API.

_extract_website_link_candidates is prefixed with an underscore, indicating it's an internal/private method. While it works (it's a staticmethod), this couples the script to implementation details that may change without notice.

For a diagnostic script this is likely acceptable, but consider whether a public wrapper or exposing this as part of the public API would be more maintainable long-term.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_link_test.py` around lines 58 - 67, The test helper
_process_file is calling the private static method
ResumeProfileExtractor._extract_website_link_candidates which couples the script
to an internal API; change the code to call a public API instead (either use an
existing public method that returns website links or add a new public static
method on ResumeProfileExtractor such as extract_website_link_candidates that
delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_link_test.py`:
- Around line 107-117: The error prints in the loop over args.files (using
path.is_file checks and the exception handler around _process_file(path)) write
to stdout and should be written to stderr; change the two print calls that
report missing file and failed processing to write to stderr (e.g., print(...,
file=sys.stderr) or sys.stderr.write) and ensure sys is imported at the top of
the script so stderr is available.
- Around line 58-67: The test helper _process_file is calling the private static
method ResumeProfileExtractor._extract_website_link_candidates which couples the
script to an internal API; change the code to call a public API instead (either
use an existing public method that returns website links or add a new public
static method on ResumeProfileExtractor such as extract_website_link_candidates
that delegates to the current private impl), then update _process_file to call
ResumeProfileExtractor.extract_website_link_candidates(text) (or the appropriate
public method) so the script relies only on the public surface rather than the
underscored internal method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc810a5d-109b-4652-9cba-eb8dc0506b05

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ccf2 and 6c17ed9.

📒 Files selected for processing (1)
  • scripts/resume_text_link_test.py

CopilotAI review requested due to automatic review settings March 9, 2026 07:55

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/resume_text_extractor.py (2)

58-67: Relying on a private method _extract_website_link_candidates.

The underscore prefix indicates this is an internal implementation detail of ResumeProfileExtractor. Private methods may change or be removed without notice, which could break this script silently.

Consider exposing a public API for this functionality if it's intended for external use, or document the coupling risk if this is acceptable for an internal diagnostic tool.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 58 - 67, The code in
_process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.

107-117: Send error messages to stderr.

Error messages are printed to stdout, which mixes them with normal output. In --json mode, this would produce invalid JSON if any file fails. CLI tools should emit errors to stderr to keep stdout clean for actual output.

♻️ Proposed fix
+import sys+
...
for file_arg in args.files:
path = Path(file_arg)
if not path.is_file():
- print(f"error: missing file: {path}")+ print(f"error: missing file: {path}", file=sys.stderr)
exit_code = 1
continue
try:
results.append(_process_file(path))
except Exception as exc: # pragma: no cover - runtime diagnostic path
- print(f"error: failed to process {path}: {exc}")+ print(f"error: failed to process {path}: {exc}", file=sys.stderr)
exit_code = 1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 107 - 117, The loop that
validates and processes args.files prints error messages to stdout (using print)
which can corrupt --json output; update the error prints in that loop (the
checks around Path(file_arg).is_file() and the except Exception handling that
wraps _process_file(path)) to write to stderr instead (e.g., use print(...,
file=sys.stderr) or an equivalent stderr logger) and ensure sys is imported at
top if not already; keep exit_code handling the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 58-67: The code in _process_file currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which is an unstable
internal API; change this by either invoking a documented public method on
ResumeProfileExtractor (e.g., a new extract_website_links or existing public
extractor method) or implement the link extraction locally in this module and
remove the private call. Update _process_file to call the chosen public function
or local helper and add a short comment about the coupling decision if you must
rely on an internal method.
- Around line 107-117: The loop that validates and processes args.files prints
error messages to stdout (using print) which can corrupt --json output; update
the error prints in that loop (the checks around Path(file_arg).is_file() and
the except Exception handling that wraps _process_file(path)) to write to stderr
instead (e.g., use print(..., file=sys.stderr) or an equivalent stderr logger)
and ensure sys is imported at top if not already; keep exit_code handling the
same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9fb3c7fc-0e36-4dd5-b816-c710f0b72d51

📥 Commits

Reviewing files that changed from the base of the PR and between 6c17ed9 and 6fa26f8.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +2
#!/usr/bin/env python3
"""Command-line helper to exercise resume text and link extraction."""

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says it adds scripts/resume_text_link_test.py, but the actual added file is scripts/resume_text_extractor.py. Please update the PR description (or rename the script) so the documentation matches what was merged.

Copilot uses AI. Check for mistakes.
Comment threadscripts/resume_text_extractor.py Outdated
Comment on lines +59 to +62
def _process_file(path: Path) -> FileResult:
raw = path.read_bytes()
text = extract_document_text(raw, filename=path.name)
link_candidates = ResumeProfileExtractor._extract_website_link_candidates(text)

CopilotAIMar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script calls ResumeProfileExtractor._extract_website_link_candidates, which is a private (underscore-prefixed) API and could change without notice. Consider exposing a small public helper (e.g., a non-underscored function/method that returns the normalized links + confidence) and have the CLI use that instead.

Suggested change
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=ResumeProfileExtractor._extract_website_link_candidates(text)
defextract_website_link_candidates(text: str) ->list[tuple[str, float]]:
"""Public helper to extract normalized website links and confidence scores."""
returnResumeProfileExtractor._extract_website_link_candidates(text)
def_process_file(path: Path) ->FileResult:
raw=path.read_bytes()
text=extract_document_text(raw, filename=path.name)
link_candidates=extract_website_link_candidates(text)

Copilot uses AI. Check for mistakes.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/resume_text_extractor.py (1)

59-61: Consider coordinating with library maintainers to expose a public API.

This wrapper calls ResumeProfileExtractor._extract_website_link_candidates, which is marked as private (leading underscore). While the wrapper itself provides a clean public interface for CLI usage, relying on private methods creates fragile coupling—the internal method's signature or behavior may change without notice.

If this extraction logic is intended for CLI/external use, consider requesting that the library expose a public method (e.g., extract_website_link_candidates) that this script can call instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/resume_text_extractor.py` around lines 59 - 61, The wrapper
extract_website_link_candidates currently calls the private
ResumeProfileExtractor._extract_website_link_candidates which creates fragile
coupling; change this to use a public API instead: coordinate with the library
maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/resume_text_extractor.py`:
- Around line 59-61: The wrapper extract_website_link_candidates currently calls
the private ResumeProfileExtractor._extract_website_link_candidates which
creates fragile coupling; change this to use a public API instead: coordinate
with the library maintainers to expose a public method (e.g.,
ResumeProfileExtractor.extract_website_link_candidates) and update this script
to call that public method, or implement a local fallback extraction routine in
this script if the public API is not yet available, and file/mention an upstream
request to add the public function so the CLI no longer depends on the
leading-underscore private method.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e16f1bf-71d0-47d1-add2-d163f62614e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa26f8 and 2cce58f.

📒 Files selected for processing (1)
  • scripts/resume_text_extractor.py

@michaelmwu
michaelmwu merged commit bc2a09c into mainMar 9, 2026
5 checks passed
@michaelmwu
michaelmwu deleted the michaelmwu/resume-text-link branch March 9, 2026 08:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@michaelmwu