Skip to content

Practical - #146

Open
sourabh1512 wants to merge 6 commits into
iam-veeramalla:mainfrom
sourabh1512:main
Open

Practical#146
sourabh1512 wants to merge 6 commits into
iam-veeramalla:mainfrom
sourabh1512:main

Conversation

@sourabh1512

@sourabh1512 sourabh1512 commented Jul 10, 2026

Copy link
Copy Markdown

Test

Summary by CodeRabbit

  • New Features
    • Added multi-criteria stock screening with ranked results and up to five top matches.
    • Added clear tabular output for matching stocks and their screening indicators.
    • Added support for updating configuration values while preserving unrelated settings.
    • Added examples for working with individual student records and student lists.
  • Improvements
    • Enhanced handling of empty, malformed, and compressed screening responses.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds a ChartInk multi-payload screener, a student dictionary example, and a configuration-file update function.

Changes

ChartInk screener integration

Layer / File(s) Summary
Screener configuration and payloads
Day-11/screener-integration.py
The script defines ChartInk request settings and multiple market-condition payloads.
Request processing and aggregation
Day-11/screener-integration.py
The script submits payloads, decodes responses, handles errors, and aggregates screener tags by stock.
Ranked result output
Day-11/screener-integration.py
The script selects up to five highest-ranked stocks and prints an aligned table.

Student data example

Layer / File(s) Summary
Student record access
Day-11/test.py
The script creates student dictionaries and prints selected names.

Configuration file update

Layer / File(s) Summary
Configuration property replacement
Day-12/fileoperations.py
updatefileProperties replaces matching configuration entries and sets MAX_CONNECTIONS to 200.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ScreenerScript
  participant ChartInk
  participant ResponseParser
  participant ResultAggregator
  ScreenerScript->>ChartInk: POST screener payload
  ChartInk-->>ScreenerScript: Return response
  ScreenerScript->>ResponseParser: Decode and parse response
  ResponseParser-->>ResultAggregator: Provide stock rows
  ResultAggregator-->>ScreenerScript: Return tagged stock results
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title "Practical" is too vague to identify the screener integration, student data structures, or file update functionality. Replace the title with a concise summary of the primary change, such as "Add ChartInk screener integration and file operations exercises".
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Warning

⚠️ This pull request has been flagged as potential spam (other-spam) by CodeRabbit slop detection and should be reviewed carefully.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 7

🧹 Nitpick comments (1)
Day-12/fileoperations.py (1)

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the trailing semicolon.

Line 3 triggers Ruff E703. Remove the semicolon.

Proposed fix
-        lines = serverConf.readlines();
+        lines = serverConf.readlines()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-12/fileoperations.py` at line 3, Remove the trailing semicolon from the
`serverConf.readlines()` assignment so the statement complies with Ruff E703.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Day-11/screener-integration.py`:
- Around line 28-35: Remove the hardcoded XSRF token and browser cookies from
the header definitions, including remember_web, ci_session, and related
authentication values. Load any required credentials through environment
variables or a local secret store instead, and rotate or revoke all exposed
sessions and tokens and purge them from repository history.
- Around line 121-123: Update the row-selection logic after ranked_rows to take
the first five entries directly from ranked_rows, removing the max_tag_count and
shortlisted_rows filtering so all ranked matches retain their ranking.
- Around line 72-74: Handle failures in the per-payload requests.post call
within the loop over PAYLOADS by catching requests.RequestException around only
that request, reporting the associated tag, and continuing to the next payload
so later requests and partial ranked output still run.
- Around line 12-28: Update the HEADERS["accept-encoding"] value to advertise
only codecs supported by the runtime; remove zstd and retain gzip, deflate, plus
Brotli only if the existing conditional decoding support is available.

In `@Day-12/fileoperations.py`:
- Around line 7-8: Update the configuration replacement logic around the
key-matching condition in the file operation flow to parse each line’s
configuration key and compare it exactly with key. Ignore comments and longer
key names such as MAX_CONNECTIONS_LIMIT, and only write the replacement when the
parsed key matches; preserve unrelated lines unchanged.
- Around line 5-10: Update the file-writing logic around the open call to build
the complete updated configuration in a temporary file located in the same
directory as filePath, then atomically replace the target using os.replace only
after the write succeeds. Ensure temporary-file cleanup on failure and preserve
the existing file permissions when required.
- Line 13: Update the call to updatefileProperties in fileoperations.py to
construct the server.conf path relative to __file__ rather than the process
working directory, preserving the existing MAX_CONNECTIONS and "200" arguments.

---

Nitpick comments:
In `@Day-12/fileoperations.py`:
- Line 3: Remove the trailing semicolon from the `serverConf.readlines()`
assignment so the statement complies with Ruff E703.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f71729ad-f8cf-4b6d-bb29-a76856322c05

📥 Commits

Reviewing files that changed from the base of the PR and between 14518ae and 1d674e3.

📒 Files selected for processing (3)
  • Day-11/screener-integration.py
  • Day-11/test.py
  • Day-12/fileoperations.py

Comment on lines +12 to +28
HEADERS = {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br, zstd",
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
"content-type": "application/json",
"origin": "https://chartink.com",
"priority": "u=1, i",
"referer": "https://chartink.com/screener/copy-rsi-above-55-and-breakout-615",
"sec-ch-ua": '"Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"macOS"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
"x-requested-with": "XMLHttpRequest",
"x-xsrf-token": "eyJpdiI6IkVhTE9nVThwZk1aY0ppQWFDMVFKOGc9PSIsInZhbHVlIjoiZ1MxQUdZL2NCYzJHWHFQelZJTElqSVFWWlBnclBZYzZ5YW9CdTRQRkRNOXZ0bmpxZHhnOWIzQ3piYXBGZkRQQVpIQU4rL2lnakFmT1YxVzJRWHRzUzlmYUJBMWtTZUxNVXc1aVg1a3M3czBwZTFmbzRQUXJvY3ZOY0gwSHZOV1AiLCJtYWMiOiJjNjhlZTJkZTg4ZmE4NDAzZDljOWQ2MjJhMjQxMzM4OGUxNzMzODU5NjM4MGVkODE4YWJmNTg2Zjg1YjAxNzJiIiwidGFnIjoiIn0=",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
git ls-files | grep -F 'Day-11/screener-integration.py' || true

echo "== file outline/size =="
wc -l Day-11/screener-integration.py
ast-grep outline Day-11/screener-integration.py || true

echo "== relevant source lines =="
sed -n '1,120p' Day-11/screener-integration.py | nl -ba

echo "== search encoding/response handling/search all script references =="
rg -n "accept-encoding|Response|br|brotli|zstd|content-encoding|response\.text|response\.json|gzip|deflate" Day-11/screener-integration.py || true

echo "== package hints =="
for f in requirements.txt pyproject.toml Pipfile setup.py setup.cfg; do
  [ -e "$f" ] && { echo "--- $f"; sed -n '1,200p' "$f"; }
done

Repository: iam-veeramalla/python-for-devops

Length of output: 1524


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== complete relevant source lines =="
sed -n '1,145p' Day-11/screener-integration.py

echo "== package hints =="
for f in requirements.txt pyproject.toml Pipfile setup.py setup.cfg; do
  if [ -e "$f" ]; then
    echo "--- $f"
    sed -n '1,200p' "$f"
  fi
done

echo "== Python dependency/runtime hints from checked files =="
python3 - <<'PY'
from pathlib import Path
for p in ["requirements.txt","pyproject.toml","Pipfile","setup.py","setup.cfg"]:
    if Path(p).exists():
        text = Path(p).read_text(errors="replace")
        print(f"\n--- {p}")
        for i,line in enumerate(text.splitlines(), 1):
            if "requests" in line.lower() or "brotli" in line.lower() or "zstandard" in line.lower() or "httpx" in line.lower():
                print(f"{i}: {line}")
PY

echo "== deterministic check: advertised encodings vs available decoders in Day-11 =="
python3 - <<'PY'
from pathlib import Path
src = Path("Day-11/screener-integration.py").read_text(errors="replace")
head = src[src.index("HEADERS = {"):src.index("}", src.index("HEADERS = {"))+1]
print("has zstd/zstandard import/decoder:", any(tok in src for tok in ["zstandard", "import zstd", "zstd."])
print("has brotli import/decoder:", "import brotmi" in src
PY

Repository: iam-veeramalla/python-for-devops

Length of output: 16873


🌐 Web query:

Python requests library content-encoding support gzip deflate brotli zstandard

💡 Result:

The Python Requests library provides automated decoding for several Content-Encoding types, delegating the underlying work to the urllib3 library [1][2]. Gzip and Deflate: Requests supports these transfer-encodings natively and decodes them automatically [2]. Brotli: Requests supports Brotli encoding automatically if a compatible Brotli library is installed in your environment [2]. Specifically, if either the 'brotli' or 'brotlicffi' package is available, Requests will include 'br' in the Accept-Encoding header and transparently handle the decoding of responses [1][3]. Zstandard (zstd): Requests does not have native support for Zstandard (zstd) decompression [4]. If the 'zstandard' library is installed, some third-party packages or system configurations may automatically include 'zstd' in the Accept-Encoding header, which can cause issues if your environment expects standard Requests behavior [4]. In such cases, users may need to manually uninstall the 'zstandard' package or explicitly override the Accept-Encoding header in their requests to exclude 'zstd' [4]. In summary, for gzip, deflate, and brotli, decompression is handled transparently, provided the necessary dependencies are present [2]. For other encodings like zstd, you may need to manage the headers or decompression manually [4].

Citations:


Do not advertise unsupported response encodings.

HEADERS["accept-encoding"] advertises zstd, but Day-11/screener-integration.py only conditionally supports Brotli and has no Zstandard decoder. Advertised encodings should be limited to codecs the intended runtime can decode; keep gzip, deflate if that is the supported baseline.

Proposed fix
-    "accept-encoding": "gzip, deflate, br, zstd",
+    "accept-encoding": "gzip, deflate",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
HEADERS = {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br, zstd",
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
"content-type": "application/json",
"origin": "https://chartink.com",
"priority": "u=1, i",
"referer": "https://chartink.com/screener/copy-rsi-above-55-and-breakout-615",
"sec-ch-ua": '"Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"macOS"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
"x-requested-with": "XMLHttpRequest",
"x-xsrf-token": "eyJpdiI6IkVhTE9nVThwZk1aY0ppQWFDMVFKOGc9PSIsInZhbHVlIjoiZ1MxQUdZL2NCYzJHWHFQelZJTElqSVFWWlBnclBZYzZ5YW9CdTRQRkRNOXZ0bmpxZHhnOWIzQ3piYXBGZkRQQVpIQU4rL2lnakFmT1YxVzJRWHRzUzlmYUJBMWtTZUxNVXc1aVg1a3M3czBwZTFmbzRQUXJvY3ZOY0gwSHZOV1AiLCJtYWMiOiJjNjhlZTJkZTg4ZmE4NDAzZDljOWQ2MjJhMjQxMzM4OGUxNzMzODU5NjM4MGVkODE4YWJmNTg2Zjg1YjAxNzJiIiwidGFnIjoiIn0=",
HEADERS = {
"accept": "*/*",
"accept-encoding": "gzip, deflate",
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
"content-type": "application/json",
"origin": "https://chartink.com",
"priority": "u=1, i",
"referer": "https://chartink.com/screener/copy-rsi-above-55-and-breakout-615",
"sec-ch-ua": '"Not;A=Brand";v="8", "Chromium";v="150", "Google Chrome";v="150"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"macOS"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/150.0.0.0 Safari/537.36",
"x-requested-with": "XMLHttpRequest",
"x-xsrf-token": "eyJpdiI6IkVhTE9nVThwZk1aY0ppQWFDMVFKOGc9PSIsInZhbHVlIjoiZ1MxQUdZL2NCYzJHWHFQelZJTElqSVFWWlBnclBZYzZ5YW9CdTRQRkRNOXZ0bmpxZHhnOWIzQ3piYXBGZkRQQVpIQU4rL2lnakFmT1YxVzJRWHRzUzlmYUJBMWtTZUxNVXc1aVg1a3M3czBwZTFmbzRQUXJvY3ZOY0gwSHZOV1AiLCJtYWMiOiJjNjhlZTJkZTg4ZmE4NDAzZDljOWQ2MjJhMjQxMzM4OGUxNzMzODU5NjM4MGVkODE4YWJmNTg2Zjg1YjAxNzJiIiwidGFnIjoiIn0=",
🧰 Tools
🪛 Betterleaks (1.7.0)

[high] 28-28: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-11/screener-integration.py` around lines 12 - 28, Update the
HEADERS["accept-encoding"] value to advertise only codecs supported by the
runtime; remove zstd and retain gzip, deflate, plus Brotli only if the existing
conditional decoding support is available.

Comment on lines +28 to +35
"x-xsrf-token": "eyJpdiI6IkVhTE9nVThwZk1aY0ppQWFDMVFKOGc9PSIsInZhbHVlIjoiZ1MxQUdZL2NCYzJHWHFQelZJTElqSVFWWlBnclBZYzZ5YW9CdTRQRkRNOXZ0bmpxZHhnOWIzQ3piYXBGZkRQQVpIQU4rL2lnakFmT1YxVzJRWHRzUzlmYUJBMWtTZUxNVXc1aVg1a3M3czBwZTFmbzRQUXJvY3ZOY0gwSHZOV1AiLCJtYWMiOiJjNjhlZTJkZTg4ZmE4NDAzZDljOWQ2MjJhMjQxMzM4OGUxNzMzODU5NjM4MGVkODE4YWJmNTg2Zjg1YjAxNzJiIiwidGFnIjoiIn0=",
}

cookie_header = (
"remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d=eyJpdiI6IkhDd05qM2pTT1JVZW0vdGVHOWNQYlE9PSIsInZhbHVlIjoiNWpJVlIzdW8vRnpWemJGWW80ZWVKelBQUmJqSUZiNy9MWW1HbXk5UEFTa2RWaEJFekNxY0F2bHRpc3M0S2hOR0JGQU5pbzZYNityTURhTGJrT25RcHVNQjR3N2dnNTNWRnhwV1o5QlNnT1ZVYlh4UWgrMWNuYlprM2VMR0tTZmoxczdRRXNFMnIzMndsaUp4MWp1bU00d0tKK3FyNnlhdDgyaytXdmZhUm91NGtLa25JcDYwYkIzTCs5M0Y0VDZnUk92ZWdVQytya0JIdkx1RGlsS1hZdzlUMEJ5RGJXSjZqb0Y3YytwK2V3VT0iLCJtYWMiOiJhOGZiOGY1ZDFiYmExNDRhNmVhMjRmZmExN2FmOGI1Y2VjMDYwZDNkNzZkOGMyOGIzYmM0OWU3M2VkZGEzZWY3IiwidGFnIjoiIn0%3D; _cc_id=ddd4893ce0c7883fd0816bb00b1dd02a; FCCDCF=%5Bnull%2Cnull%2Cnull%2Cnull%2Cnull%2Cnull%2C%5B%5B32%2C%22%5B%5C%226f1b27a0-7d11-4a14-98ae-03a35fed3e2a%5C%22%2C%5B1784555417%2C262000000%5D%5D%22%5D%5D%5D; FCNEC=%5B%5B%22AKsRol-TAHbJACJY4lTrE5ZSlvrKAxjPJXn5e-ns2BOn-gqwuibhr6NbHGZUaZzRF80Ca7kNMBb7QAhsRqSehMMwoudMOCcEK5KcwrhEfRWcCXflfJ6qWQ5mePeAXNlA69Fav4cxcIwmIYxtne0C09Q3gSkT2v11bg%3D%3D%22%5D%5D; __utma=102564947.1968319544.1784554512.1784685434.1784685434.1; __utmz=102564947.1784685434.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _gid=GA1.2.1711244705.1785667224; _ga=GA1.1.1968319544.1784554512; XSRF-TOKEN=eyJpdiI6IkVhTE9nVThwZk1aY0ppQWFDMVFKOGc9PSIsInZhbHVlIjoiZ1MxQUdZL2NCYzJHWHFQelZJTElqSVFWWlBnclBZYzZ5YW9CdTRQRkRNOXZ0bmpxZHhnOWIzQ3piYXBGZkRQQVpIQU4rL2lnakFmT1YxVzJRWHRzUzlmYUJBMWtTZUxNVXc1aVg1a3M3czBwZTFmbzRQUXJvY3ZOY0gwSHZOV1AiLCJtYWMiOiJjNjhlZTJkZTg4ZmE4NDAzZDljOWQ2MjJhMjQxMzM4OGUxNzMzODU5NjM4MGVkODE4YWJmNTg2Zjg1YjAxNzJiIiwidGFnIjoiIn0%3D; ci_session=eyJpdiI6IkY1c09MOXdNc2JPcTZSUlRKNUNSS0E9PSIsInZhbHVlIjoiYjI0dG84dXNpTzV2czladlhSWC9qZmdEa0Ixa3JxTTRXTmU4QStEdUZTNmU5UURyYmpqbkk5VjREb0tYbUxTcE5NcEdXa09pdTdCQVQ1Qy9wMkIzNVgvQlMwU1Z6eEZHbmJDbXRBek1vREQ3RHF4VGs1U2hpMFJYaHlsNmdTZ2giLCJtYWMiOiIyNzZiYzMzNGRjOTlkYTJmNjZkN2Q5YzYyYWRmMTUyMGZhMWYwMDA1ZTQ3M2FhYmYxNzEwZmI5NjAzNWY5NjE4IiwidGFnIjoiIn0%3D; __gads=ID=a475dc11d13edfcf:T=1784555440:RT=1785667724:S=ALNI_MYui5MgqrqdpMh-ReKIEte6_hI-uA; __gpi=UID=000014cd24fad536:T=1784555440:RT=1785667724:S=ALNI_MZGgCFV-utYaaRCbqopFGIu-JkQow; __eoi=ID=262f680056f8b3e7:T=1784555440:RT=1785667724:S=AA-Afja56EFTSdPZv4hb308AWKUH; _ga_7P3KPC3ZPP=GS2.1.s1785665055$o7$g1$t1785667725$j33$l0$h0"
)

HEADERS["cookie"] = cookie_header

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Remove the committed session credentials.

Line 28 embeds an XSRF token. Lines 31-35 embed remember_web, ci_session, and related browser cookies. An attacker can replay an unexpired authenticated session against ChartInk.

Revoke the exposed sessions and tokens. Remove these values from the repository and its history. Load required credentials from a local secret store or environment variables.

🧰 Tools
🪛 Betterleaks (1.7.0)

[high] 28-28: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


[high] 32-32: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-11/screener-integration.py` around lines 28 - 35, Remove the hardcoded
XSRF token and browser cookies from the header definitions, including
remember_web, ci_session, and related authentication values. Load any required
credentials through environment variables or a local secret store instead, and
rotate or revoke all exposed sessions and tokens and purge them from repository
history.

Source: Linters/SAST tools

Comment on lines +72 to +74
for tag, payload in PAYLOADS.items():
response = requests.post(URL, headers=HEADERS, cookies=COOKIES, json=payload, timeout=30)
print(f"\nTag: {tag} | Status code: {response.status_code}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate file:"
fd -a 'screener-integration.py' . || true

file="$(fd 'screener-integration.py' . | head -n1 || true)"
if [ -n "${file:-}" ]; then
  echo "File: $file"
  wc -l "$file"
  echo "--- outline ---"
  ast-grep outline "$file" || true
  echo "--- relevant lines 1-140 ---"
  sed -n '1,140p' "$file" | nl -ba
fi

echo "Search for exception handling around requests.post:"
rg -n "requests\.post|RequestException|except .*Exception|PAYLOADS|for tag" . || true

echo "Git diff stat/name:"
git diff --stat || true
git diff -- "$file" | sed -n '1,220p' || true

Repository: iam-veeramalla/python-for-devops

Length of output: 1574


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="$(fd 'screener-integration.py' . | head -n1 || true)"
if [ -n "${file:-}" ]; then
  python3 - <<'PY' "$file"
import ast, sys
path=sys.argv[1]
with open(path, 'rb') as f:
    tree=ast.parse(f.read(), filename=path, type_comments=True)
print("top-level statements:", len(tree.body))
for node in ast.walk(tree):
    if isinstance(node, ast.For) and isinstance(node.iter, ast.Attribute) and node.iter.attr == "items":
        line=node.lineno
        starts=[start.lineno for start in [node.body[0], node.orelse[0]] if hasattr(start,'lineno')]
        print(f"For at line {line} body starts at line {node.body[0].lineno}, orelse starts at line {node.orelse[0].lineno if node.orelse else None}")
        # determine indentation for first statement in orelse if any
        stmts=[]
        for i,body in enumerate(["for"]):
            pass
        for child in node.body+node.orelse:
            if isinstance(child, ast.Call) and isinstance(child.func, ast.Attribute):
                print(f"child call {ast.get_source_segment(open(path), child)!r} at line {child.lineno}")
            if isinstance(child, ast.Try):
                print(f"TRY at line {child.lineno}")
PY
fi

Repository: iam-veeramalla/python-for-devops

Length of output: 195


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="./Day-11/screener-integration.py"
echo "--- file size and imports/header ---"
wc -l "$file"
head -n 90 "$file" | awk '{printf "%4d\t%s\n", NR, $0}'

echo "--- search exception/request handling ---"
grep -nE "requests\.post|RequestException|except\s+.*Exception|try:|continue|break|for\s+tag\s+in\s+PAYLOADS" "$file" || true

echo "--- static indentation/source around loop ---"
python3 - <<'PY'
from pathlib import Path
p=Path("Day-11/screener-integration.py")
source=p.read_text().splitlines()
for i,line in enumerate(source[:95],1):
    if "for tag" in line or "requests.post" in line or i in range(70,90):
        print(f"{i:4}: [{line[:80]}]")
PY

Repository: iam-veeramalla/python-for-devops

Length of output: 16246


Handle request failures for each payload.

The per-payload requests.post() call is before the parsing try block. If the request raises requests.RequestException, the remaining payloads do not run and no partial ranked output is printed. Wrap only the request in requests.RequestException, report the failed tag, and continue with the remaining payloads.

Proposed fix
 for tag, payload in PAYLOADS.items():
-    response = requests.post(URL, headers=HEADERS, cookies=COOKIES, json=payload, timeout=30)
+    try:
+        response = requests.post(URL, headers=HEADERS, cookies=COOKIES, json=payload, timeout=30)
+    except requests.RequestException as exc:
+        print(f"Unable to request {tag}: {exc}")
+        continue
     print(f"\nTag: {tag} | Status code: {response.status_code}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for tag, payload in PAYLOADS.items():
response = requests.post(URL, headers=HEADERS, cookies=COOKIES, json=payload, timeout=30)
print(f"\nTag: {tag} | Status code: {response.status_code}")
for tag, payload in PAYLOADS.items():
try:
response = requests.post(URL, headers=HEADERS, cookies=COOKIES, json=payload, timeout=30)
except requests.RequestException as exc:
print(f"Unable to request {tag}: {exc}")
continue
print(f"\nTag: {tag} | Status code: {response.status_code}")
🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 72-72: Request-controlled URL passed to requests; validate against an allowlist to prevent SSRF.
Context: requests.post(URL, headers=HEADERS, cookies=COOKIES, json=payload, timeout=30)
Note: [CWE-918] Server-Side Request Forgery (SSRF).

(ssrf-requests)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-11/screener-integration.py` around lines 72 - 74, Handle failures in the
per-payload requests.post call within the loop over PAYLOADS by catching
requests.RequestException around only that request, reporting the associated
tag, and continuing to the next payload so later requests and partial ranked
output still run.

Comment on lines +121 to +123
max_tag_count = max((len(row["tags"]) for row in ranked_rows), default=0)
shortlisted_rows = [row for row in ranked_rows if len(row["tags"]) == max_tag_count]
selected_rows = shortlisted_rows[:5]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Select the first five ranked rows.

Lines 121-123 discard every row below the highest tag count. If one stock has the most tags, the table prints only that stock even when other ranked matches exist.

Select the first five rows from ranked_rows.

Proposed fix
-    max_tag_count = max((len(row["tags"]) for row in ranked_rows), default=0)
-    shortlisted_rows = [row for row in ranked_rows if len(row["tags"]) == max_tag_count]
-    selected_rows = shortlisted_rows[:5]
+    selected_rows = ranked_rows[:5]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
max_tag_count = max((len(row["tags"]) for row in ranked_rows), default=0)
shortlisted_rows = [row for row in ranked_rows if len(row["tags"]) == max_tag_count]
selected_rows = shortlisted_rows[:5]
selected_rows = ranked_rows[:5]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-11/screener-integration.py` around lines 121 - 123, Update the
row-selection logic after ranked_rows to take the first five entries directly
from ranked_rows, removing the max_tag_count and shortlisted_rows filtering so
all ranked matches retain their ranking.

Comment thread Day-12/fileoperations.py
Comment on lines +5 to +10
with open(filePath,"w") as serverConf:
for line in lines:
if key in line:
serverConf.write(key+"="+value+"\n")
else:
serverConf.write(line)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repo files matching fileoperations.py =="
fd -a 'fileoperations\.py$' . || true

echo "== target file contents with line numbers =="
if [ -f Day-12/fileoperations.py ]; then
  cat -n Day-12/fileoperations.py
fi

echo "== references to update/create/write config functions =="
rg -n "def |open\\(|write\\(|update|create|conf" Day-12/fileoperations.py . 2>/dev/null | head -200 || true

echo "== relevant imports/usages from nearby tracked files =="
git ls-files Day-12 | xargs -r -n1 sh -c 'echo "--- $0"; sed -n "1,160p" "$0"' 2>/dev/null | head -300

Repository: iam-veeramalla/python-for-devops

Length of output: 14944


Write the configuration atomically.

open(filePath, "w") truncates server.conf before the rewrite loop starts. If the process is interrupted or a write fails, the function leaves the target empty or partially written. Write the updated content to a temporary file in the same directory, then replace server.conf with os.replace; preserve the original file permissions if they matter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-12/fileoperations.py` around lines 5 - 10, Update the file-writing logic
around the open call to build the complete updated configuration in a temporary
file located in the same directory as filePath, then atomically replace the
target using os.replace only after the write succeeds. Ensure temporary-file
cleanup on failure and preserve the existing file permissions when required.

Comment thread Day-12/fileoperations.py
Comment on lines +7 to +8
if key in line:
serverConf.write(key+"="+value+"\n")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Match the configuration key exactly.

key in line also matches comments and longer keys. For example, MAX_CONNECTIONS matches # MAX_CONNECTIONS and MAX_CONNECTIONS_LIMIT=.... Line 8 can then overwrite unrelated configuration. Compare the parsed key before writing.

Proposed fix
-            if key in line:
+            key_part, separator, _ = line.partition("=")
+            if separator and key_part.strip() == key:
                 serverConf.write(key+"="+value+"\n")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if key in line:
serverConf.write(key+"="+value+"\n")
key_part, separator, _ = line.partition("=")
if separator and key_part.strip() == key:
serverConf.write(key+"="+value+"\n")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-12/fileoperations.py` around lines 7 - 8, Update the configuration
replacement logic around the key-matching condition in the file operation flow
to parse each line’s configuration key and compare it exactly with key. Ignore
comments and longer key names such as MAX_CONNECTIONS_LIMIT, and only write the
replacement when the parsed key matches; preserve unrelated lines unchanged.

Comment thread Day-12/fileoperations.py
serverConf.write(line)


updatefileProperties("server.conf","MAX_CONNECTIONS","200") No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | sed -n '1,120p'

echo
echo "Day-12 candidates:"
fd -a . Day-12 2>/dev/null | sed 's#^\./##' | sed -n '1,120p'

echo
if [ -f Day-12/fileoperations.py ]; then
  echo "Day-12/fileoperations.py outline:"
  ast-grep outline Day-12/fileoperations.py || true
  echo
  echo "Day-12/fileoperations.py contents:"
  cat -n Day-12/fileoperations.py
fi

echo
if [ -f Day-12/fileoperations.py ]; then
  echo "Read/write usages in Day-12/fileoperations.py:"
  python3 - <<'PY'
from pathlib import Path
p=Path('Day-12/fileoperations.py')
text=p.read_text()
for i,line in enumerate(text.splitlines(),1):
    if 'updatefileProperties' in line or 'open(' in line or 'readlines' in line or 'readline' in line or 'write' in line or 'read(' in line:
        print(f'{i}: {line}')
PY
fi

echo
echo "server.conf file:"
if [ -f Day-12/server.conf ]; then
 cat -n Day-12/server.conf
else
 echo "Day-12/server.conf not found"
fi

echo
echo "Python path resolution probe:"
python3 - <<'PY'
from pathlib import Path
for d in ["repo_root", "Day-12", "/tmp"]:
    print(d, "->", Path(d).resolve(), "Day-12/server.conf exists from cwd?", (Path(d).resolve()/"Day-12"/"server.conf").exists())
    print(d, "->", Path("server.conf").resolve(), "server.conf exists from cwd?", Path("server.conf").resolve().exists())
PY

Repository: iam-veeramalla/python-for-devops

Length of output: 4741


Resolve server.conf relative to __file__.

updatefileProperties("server.conf", ...) uses the process working directory, while the repository file is Day-12/server.conf. Running python Day-12/fileoperations.py from the repository root makes open() look for server.conf in the repository root instead of Day-12, so the call fails before the property update.

Proposed fix
+from pathlib import Path
+
-updatefileProperties("server.conf","MAX_CONNECTIONS","200")
+updatefileProperties(
+    Path(__file__).resolve().with_name("server.conf"),
+    "MAX_CONNECTIONS",
+    "200",
+)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
updatefileProperties("server.conf","MAX_CONNECTIONS","200")
from pathlib import Path
updatefileProperties(
Path(__file__).resolve().with_name("server.conf"),
"MAX_CONNECTIONS",
"200",
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Day-12/fileoperations.py` at line 13, Update the call to updatefileProperties
in fileoperations.py to construct the server.conf path relative to __file__
rather than the process working directory, preserving the existing
MAX_CONNECTIONS and "200" arguments.

Sign up for free to 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.

1 participant