chefmate 1.0.1__tar.gz → 1.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) [2025] [Anuj Kumar Sah]
3
+ Copyright (c) 2025 Anuj Kumar Sah
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: chefmate
3
+ Version: 1.0.2
4
+ Summary: Automation tool for CodeChef
5
+ Home-page: https://github.com/Anuj-72/ChefMate
6
+ Author: Anuj Kumar Sah
7
+ Author-email: Anuj Kumar Sah <anujsah282005@gmail.com>
8
+ License: MIT
9
+ Keywords: CodeChef,CLI,automation,competitive-programming
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Build Tools
15
+ Requires-Python: >=3.7
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Dynamic: author
19
+ Dynamic: home-page
20
+ Dynamic: license-file
21
+ Dynamic: requires-python
22
+
23
+ # ChefMate
24
+
25
+ ![Logo](assets/CHEFMATE.png)
26
+
27
+ ChefMate is a CLI tool for automating CodeChef tasks via an interactive menu-driven interface. It streamlines the workflow of logging in, opening contests, solving problems, running demo test cases, submitting solutions, and tracking problem statuses in real time.
28
+
29
+ ## Features
30
+
31
+ - **Interactive Mode**: User-friendly, arrow-key-driven menu
32
+ - **Automated Login**: Seamlessly sign into CodeChef
33
+ - **Contest Management**: Open contests by ID directly in browser
34
+ - **Problem Solving Support**: Scaffold and open solution files locally
35
+ - **Demo Test Case Checking**: Run and verify sample tests before submission
36
+ - **Automated Submission**: Submit solutions without leaving the terminal
37
+ - **Problem Tracker**: View status (✅ done | 🟡 pending | ❌ wrong)
38
+ - **Configuration Management**: Easily reconfigure user preferences
39
+ - **Clear Terminal**: Wipe the screen for a fresh view
40
+
41
+ ## Installation
42
+
43
+ You don’t need to clone any repository — just install via pip:
44
+
45
+ ```bash
46
+ pip install chefmate
47
+ ```
48
+
49
+ That’s it!
50
+
51
+ ## Usage
52
+
53
+ Run ChefMate in interactive mode:
54
+
55
+ ```bash
56
+ python main.py interactive
57
+ ```
58
+
59
+ > If you have set up an entry point, you can also run:
60
+
61
+ ```bash
62
+ chefmate interactive
63
+ ```
64
+
65
+ ## Initial Configuration
66
+
67
+ On first run, ChefMate will prompt you to configure key settings:
68
+
69
+ - **Username**: Your CodeChef username
70
+ - **Password**: Your CodeChef password (input hidden)
71
+ - **Default Solution Path**: Local directory or file path pattern for solutions
72
+ - **Chrome User Data Directory** (optional): Path to Chrome profile data
73
+ - **Chrome Profile** (optional): Profile name within Chrome
74
+ - **Preferred Language**: Language for submissions (C++, Python 3, Java, etc.)
75
+ - **Preferred Editor**: Editor to open solution files (default, VS Code, Sublime, etc.)
76
+
77
+ ![First Configure](assets/First_Configure.gif)
78
+
79
+ ## Interactive Mode Options
80
+
81
+ When you launch interactive mode, you’ll see a menu:
82
+
83
+ ```text
84
+ ==================================================
85
+ ChefMate Interactive Mode
86
+ ==================================================
87
+ ```
88
+
89
+ Use arrow keys to navigate and Enter to select any of the following:
90
+
91
+ | Option | Description | Example GIF/Screenshot |
92
+ |--------------------------------|-------------------------------------------------------|---------------------------------------------|
93
+ | **Login** | Authenticate with CodeChef | ![Logging In](assets/Logging_In.gif) |
94
+ | **Open Contest** | Open a CodeChef contest by ID in your browser | ![Open Contest](assets/Open_Contest_Page.gif) |
95
+ | **Solve Problems** | Scaffold and open solution templates locally | ![Solve Problems](assets/Solve_Problems.gif) |
96
+ | **Check Demo test cases** | Run sample tests on your solution | ![Demo Tests](assets/Demo_Test_Cases.gif) |
97
+ | **Submit Solution** | Submit your solution to CodeChef | ![Submitting Solution](assets/Submitting_Solution.gif) |
98
+ | **Problem Tracker** | View current status of each problem | ![Tracker](assets/Problem_Tracker.png) |
99
+ | **Re-configure ChefMate** | Update any configuration options | |
100
+ | **Clear Terminal** | Clear your terminal screen | |
101
+ | **Logout** | Sign out of your CodeChef session | |
102
+ | **Exit / Logout and Exit** | Quit interactive mode (and logout if selected) | |
103
+
104
+ ## Visual Walkthrough
105
+
106
+ ### Start ChefMate
107
+
108
+ ![Start ChefMate](assets/Start_ChefMate.gif)
109
+
110
+ ### Logging In
111
+
112
+ ![Logging In](assets/Logging_In.gif)
113
+
114
+ ### Opening a Contest
115
+
116
+ ![Open Contest](assets/Open_Contest_Page.gif)
117
+
118
+ ### Solving Problems
119
+
120
+ ![Solve Problems](assets/Solve_Problems.gif)
121
+
122
+ ### Checking Demo Test Cases
123
+
124
+ ![Demo Test Cases](assets/Demo_Test_Cases.gif)
125
+
126
+ ### Submitting a Solution
127
+
128
+ ![Submitting Solution](assets/Submitting_Solution.gif)
129
+
130
+ ### Problem Tracker
131
+
132
+ ![Problem Tracker](assets/Problem_Tracker.png)
133
+
134
+ ## License
135
+
136
+ This project is released under the MIT License. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,114 @@
1
+ # ChefMate
2
+
3
+ ![Logo](assets/CHEFMATE.png)
4
+
5
+ ChefMate is a CLI tool for automating CodeChef tasks via an interactive menu-driven interface. It streamlines the workflow of logging in, opening contests, solving problems, running demo test cases, submitting solutions, and tracking problem statuses in real time.
6
+
7
+ ## Features
8
+
9
+ - **Interactive Mode**: User-friendly, arrow-key-driven menu
10
+ - **Automated Login**: Seamlessly sign into CodeChef
11
+ - **Contest Management**: Open contests by ID directly in browser
12
+ - **Problem Solving Support**: Scaffold and open solution files locally
13
+ - **Demo Test Case Checking**: Run and verify sample tests before submission
14
+ - **Automated Submission**: Submit solutions without leaving the terminal
15
+ - **Problem Tracker**: View status (✅ done | 🟡 pending | ❌ wrong)
16
+ - **Configuration Management**: Easily reconfigure user preferences
17
+ - **Clear Terminal**: Wipe the screen for a fresh view
18
+
19
+ ## Installation
20
+
21
+ You don’t need to clone any repository — just install via pip:
22
+
23
+ ```bash
24
+ pip install chefmate
25
+ ```
26
+
27
+ That’s it!
28
+
29
+ ## Usage
30
+
31
+ Run ChefMate in interactive mode:
32
+
33
+ ```bash
34
+ python main.py interactive
35
+ ```
36
+
37
+ > If you have set up an entry point, you can also run:
38
+
39
+ ```bash
40
+ chefmate interactive
41
+ ```
42
+
43
+ ## Initial Configuration
44
+
45
+ On first run, ChefMate will prompt you to configure key settings:
46
+
47
+ - **Username**: Your CodeChef username
48
+ - **Password**: Your CodeChef password (input hidden)
49
+ - **Default Solution Path**: Local directory or file path pattern for solutions
50
+ - **Chrome User Data Directory** (optional): Path to Chrome profile data
51
+ - **Chrome Profile** (optional): Profile name within Chrome
52
+ - **Preferred Language**: Language for submissions (C++, Python 3, Java, etc.)
53
+ - **Preferred Editor**: Editor to open solution files (default, VS Code, Sublime, etc.)
54
+
55
+ ![First Configure](assets/First_Configure.gif)
56
+
57
+ ## Interactive Mode Options
58
+
59
+ When you launch interactive mode, you’ll see a menu:
60
+
61
+ ```text
62
+ ==================================================
63
+ ChefMate Interactive Mode
64
+ ==================================================
65
+ ```
66
+
67
+ Use arrow keys to navigate and Enter to select any of the following:
68
+
69
+ | Option | Description | Example GIF/Screenshot |
70
+ |--------------------------------|-------------------------------------------------------|---------------------------------------------|
71
+ | **Login** | Authenticate with CodeChef | ![Logging In](assets/Logging_In.gif) |
72
+ | **Open Contest** | Open a CodeChef contest by ID in your browser | ![Open Contest](assets/Open_Contest_Page.gif) |
73
+ | **Solve Problems** | Scaffold and open solution templates locally | ![Solve Problems](assets/Solve_Problems.gif) |
74
+ | **Check Demo test cases** | Run sample tests on your solution | ![Demo Tests](assets/Demo_Test_Cases.gif) |
75
+ | **Submit Solution** | Submit your solution to CodeChef | ![Submitting Solution](assets/Submitting_Solution.gif) |
76
+ | **Problem Tracker** | View current status of each problem | ![Tracker](assets/Problem_Tracker.png) |
77
+ | **Re-configure ChefMate** | Update any configuration options | |
78
+ | **Clear Terminal** | Clear your terminal screen | |
79
+ | **Logout** | Sign out of your CodeChef session | |
80
+ | **Exit / Logout and Exit** | Quit interactive mode (and logout if selected) | |
81
+
82
+ ## Visual Walkthrough
83
+
84
+ ### Start ChefMate
85
+
86
+ ![Start ChefMate](assets/Start_ChefMate.gif)
87
+
88
+ ### Logging In
89
+
90
+ ![Logging In](assets/Logging_In.gif)
91
+
92
+ ### Opening a Contest
93
+
94
+ ![Open Contest](assets/Open_Contest_Page.gif)
95
+
96
+ ### Solving Problems
97
+
98
+ ![Solve Problems](assets/Solve_Problems.gif)
99
+
100
+ ### Checking Demo Test Cases
101
+
102
+ ![Demo Test Cases](assets/Demo_Test_Cases.gif)
103
+
104
+ ### Submitting a Solution
105
+
106
+ ![Submitting Solution](assets/Submitting_Solution.gif)
107
+
108
+ ### Problem Tracker
109
+
110
+ ![Problem Tracker](assets/Problem_Tracker.png)
111
+
112
+ ## License
113
+
114
+ This project is released under the MIT License. See [LICENSE](LICENSE) for details.
@@ -27,6 +27,7 @@ from selenium.webdriver.common.by import By
27
27
  from selenium.webdriver.common.keys import Keys
28
28
  from chefmate.browser_manager import BrowserManager
29
29
  from selenium.webdriver.support.ui import WebDriverWait
30
+ from selenium.common.exceptions import TimeoutException
30
31
  from selenium.webdriver.support import expected_conditions as EC
31
32
  # ------------------------------------------------------------------
32
33
 
@@ -124,7 +125,12 @@ class ChefMate:
124
125
 
125
126
  def goto_dashboard(self):
126
127
  self.browser.driver.get("https://www.codechef.com/dashboard")
127
- WebDriverWait(self.browser.driver, 10).until(EC.presence_of_element_located((By.XPATH, "//img[contains(@alt, 'CodeChef Logo')]")))
128
+ try:
129
+ WebDriverWait(self.browser.driver, 15).until(
130
+ EC.presence_of_element_located((By.XPATH, "//img[contains(@alt, 'CodeChef Logo')]"))
131
+ )
132
+ except TimeoutException:
133
+ print(f"{Fore.RED} Failed to load dashboard page in 15seconds. Slow Internet \n")
128
134
  print(f"{Fore.GREEN} Dashboard opened successfully! \u2714\n")
129
135
 
130
136
  def display_logo(self):
@@ -175,6 +181,7 @@ class ChefMate:
175
181
  self.contest_id = None # Add this line to store the contest ID
176
182
  self.contest_dir = None # Add this line to store the contest directory
177
183
  self.problem_status = {}
184
+ self.logged_in = False
178
185
 
179
186
  def setup(self):
180
187
  """Setup ChefMate configuration"""
@@ -352,10 +359,13 @@ class ChefMate:
352
359
  dashboard_URL = "https://www.codechef.com/dashboard"
353
360
  self.browser.driver.get(dashboard_URL)
354
361
  try:
355
- WebDriverWait(self.browser.driver, 10).until(
362
+ WebDriverWait(self.browser.driver, 15).until(
356
363
  EC.presence_of_element_located((By.XPATH, "//img[contains(@alt, 'CodeChef Logo') ]"))
357
364
  )
358
365
  return self.browser.driver.current_url == dashboard_URL
366
+ except TimeoutException:
367
+ print(f"{Fore.RED} Failed to load dashboard page in 15seconds. Slow Internet \n")
368
+ return False
359
369
  except: return False
360
370
 
361
371
  def login(self, first_login: bool = False):
@@ -367,6 +377,7 @@ class ChefMate:
367
377
 
368
378
  if self.already_logged_in():
369
379
  print(f"{Fore.GREEN} Already logged in \u2714\n")
380
+ self.logged_in = True
370
381
  return True
371
382
 
372
383
  username = self.config.get("username", "")
@@ -382,15 +393,23 @@ class ChefMate:
382
393
  self.browser.driver.get("https://www.codechef.com/login")
383
394
  self.type_writer(" Loggin in ... ")
384
395
 
385
- WebDriverWait(self.browser.driver, 10).until(
386
- EC.element_to_be_clickable((By.ID, "edit-name"))
387
- )
396
+ try:
397
+ WebDriverWait(self.browser.driver, 15).until(
398
+ EC.element_to_be_clickable((By.ID, "edit-name"))
399
+ )
400
+ except TimeoutException:
401
+ print(f"{Fore.RED} Failed to load login page in 15seconds. Slow Internet, Please Try again\n")
402
+ return False
388
403
 
389
404
  if first_login:
390
405
  self.browser.driver.refresh()
391
- WebDriverWait(self.browser.driver, 10).until(
392
- EC.element_to_be_clickable((By.ID, "edit-name"))
393
- )
406
+ try:
407
+ WebDriverWait(self.browser.driver, 15).until(
408
+ EC.element_to_be_clickable((By.ID, "edit-name"))
409
+ )
410
+ except TimeoutException:
411
+ print(f"{Fore.RED} Failed to load login page in 15seconds. Slow Internet, Please Try again\n")
412
+ return False
394
413
 
395
414
  u_box = self.browser.driver.find_element(By.ID, "edit-name")
396
415
  u_box.send_keys(Keys.CONTROL + "a" + Keys.BACKSPACE)
@@ -401,7 +420,7 @@ class ChefMate:
401
420
  p_box.send_keys(password + Keys.RETURN)
402
421
 
403
422
  max_wait_time = 20
404
- interval = 2
423
+ interval = 5
405
424
  elapsed_time = 0
406
425
 
407
426
  # For slow networks, retry login
@@ -411,6 +430,7 @@ class ChefMate:
411
430
  EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, '_content__container')]")
412
431
  ))
413
432
  print(f"{Fore.GREEN} Successfully loaded Dashboard \u2714\n{Style.RESET_ALL}")
433
+ self.logged_in = True
414
434
  return True
415
435
  except:
416
436
  elapsed_time += interval
@@ -425,18 +445,25 @@ class ChefMate:
425
445
  if not self.browser.driver:
426
446
  print(f"{Fore.YELLOW} No active browser session.\n")
427
447
  return
428
-
448
+
429
449
  self.type_writer(" Logging out ... ")
430
450
 
431
451
  self.browser.driver.get("https://www.codechef.com/logout")
432
452
  try:
433
- WebDriverWait(self.browser.driver, 10).until(
453
+ WebDriverWait(self.browser.driver, 15).until(
434
454
  EC.presence_of_element_located((By.XPATH, "//img[contains(@alt, 'CodeChef Logo')]"))
435
455
  )
436
456
  print(f"{Fore.GREEN} Logged out successfully \u2714\n")
457
+ self.logged_in = False
458
+ return
459
+ except TimeoutException:
460
+ print(f"{Fore.RED} Logout timed out, has waited 15 seconds. Please check your internet connection and try again.\n")
461
+ return
437
462
  except:
438
463
  print(f"{Fore.YELLOW} Logout status unclear, closing browser anyway.\n")
439
-
464
+ self.logged_in = False
465
+ return
466
+
440
467
  def quit(self):
441
468
  """Quit the browser and end session"""
442
469
  if self.browser.driver:
@@ -452,8 +479,10 @@ class ChefMate:
452
479
  Prompts for contest ID and division, opens contest page and all problem tabs.
453
480
  """
454
481
 
455
- if not self.already_logged_in():
456
- self.login()
482
+ if not self.logged_in:
483
+ self.type_writer(" Logging in before opening contest ... ")
484
+ if not self.login():
485
+ return False
457
486
 
458
487
  division_map = {1: 'A', 2: 'B', 3: 'C', 4: 'D'}
459
488
 
@@ -470,9 +499,11 @@ class ChefMate:
470
499
 
471
500
  self.browser.driver.get(contest_url)
472
501
  try:
473
- WebDriverWait(self.browser.driver, 10).until(
502
+ WebDriverWait(self.browser.driver, 15).until(
474
503
  EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, 'problem-table')]"))
475
504
  )
505
+ except TimeoutException:
506
+ print(f"{Fore.RED} Failed to load problems in 15seconds. Slow Internet, Please Try again\n")
476
507
  except:
477
508
  print(f"{Fore.YELLOW} Contest page looks different than expected, but continuing...")
478
509
 
@@ -483,6 +514,8 @@ class ChefMate:
483
514
  EC.presence_of_element_located((By.CLASS_NAME, "dataTable"))
484
515
  )
485
516
  links = table.find_elements(By.TAG_NAME, "a")
517
+ except TimeoutException:
518
+ print(f"{Fore.RED} Failed to load problems in 10seconds. Slow Internet, Please Try again\n")
486
519
  except:
487
520
  links = self.browser.driver.find_elements(By.XPATH, "//a[contains(@href, 'problems')]")
488
521
 
@@ -575,7 +608,7 @@ class ChefMate:
575
608
  except Exception as e:
576
609
  print(f"{Fore.RED} Error selecting language: {e}")
577
610
  return False
578
-
611
+
579
612
  def _load_code(self, code_text):
580
613
  """Load code into editor"""
581
614
  try:
@@ -606,12 +639,6 @@ class ChefMate:
606
639
  def submit_solution(self, problem_num: int = None):
607
640
  # Submit solution for a problem
608
641
 
609
- curr_url = self.browser.driver.current_url
610
- if not self.login():
611
- self.login()
612
-
613
- self.browser.driver.get(curr_url)
614
-
615
642
  if not self.problems or not self.tabs:
616
643
  print(f"{Fore.RED} No problems loaded. Please open contest tab first.")
617
644
  return False
@@ -656,9 +683,18 @@ class ChefMate:
656
683
  text_input.send_keys(Keys.CONTROL + Keys.ENTER)
657
684
  self.type_writer(" Submitting the Code ... ")
658
685
 
659
- WebDriverWait(self.browser.driver, 20).until(
660
- EC.presence_of_element_located((By.XPATH, "//div[contains(@class, '_run__container')]"))
661
- )
686
+ try:
687
+ WebDriverWait(self.browser.driver, 20).until(
688
+ EC.presence_of_element_located((By.XPATH, "//div[contains(@class, '_run__container')]"))
689
+ )
690
+ except TimeoutException:
691
+ print(f"{Fore.RED} Submission timed out, has waited 20 seconds. Please check your internet connection and try again.\n")
692
+ return False
693
+ except Exception as e:
694
+ print(f"{Fore.RED} Error submitting code: {e}")
695
+ return False
696
+
697
+ # Wait for the verdict to appear
662
698
 
663
699
  verdict_in_run_container = self.browser.driver.find_element(By.XPATH, "//div[contains(@class, '_run__container')]").text
664
700
  if 'Error' in verdict_in_run_container or 'limit' in verdict_in_run_container.lower():
@@ -666,9 +702,16 @@ class ChefMate:
666
702
  return False
667
703
 
668
704
  # Wait for the verdict table to appear
669
- WebDriverWait(self.browser.driver, 20).until(
670
- EC.presence_of_element_located((By.XPATH, "//table[contains(@class, 'status-table')]"))
671
- )
705
+ try:
706
+ WebDriverWait(self.browser.driver, 20).until(
707
+ EC.presence_of_element_located((By.XPATH, "//table[contains(@class, 'status-table')]"))
708
+ )
709
+ except TimeoutException:
710
+ print(f"{Fore.RED} Submission timed out, has waited 20 seconds. Please check your internet connection and try again.\n")
711
+ return False
712
+ except Exception as e:
713
+ print(f"{Fore.RED} Error submitting code: {e}")
714
+ return False
672
715
 
673
716
  # Extract table data
674
717
  table_element = self.browser.driver.find_element(By.XPATH, "//table[contains(@class, 'status-table')]")
@@ -814,9 +857,16 @@ class ChefMate:
814
857
  try:
815
858
  text_input = self.browser.driver.find_element(By.CSS_SELECTOR, "textarea.ace_text-input")
816
859
  text_input.send_keys(Keys.CONTROL + Keys.SHIFT + Keys.ENTER)
817
- WebDriverWait(self.browser.driver, 20).until(
818
- EC.presence_of_element_located((By.XPATH, "//div[contains(@class, '_output-item__value_')]"))
819
- )
860
+ try:
861
+ WebDriverWait(self.browser.driver, 20).until(
862
+ EC.presence_of_element_located((By.XPATH, "//div[contains(@class, '_output-item__value_')]"))
863
+ )
864
+ except TimeoutException:
865
+ print(f"{Fore.RED} Timed out waiting for test cases to run.")
866
+ return False
867
+ except Exception as e:
868
+ print(f"{Fore.RED} Error waiting for test cases to run: {e}")
869
+ return False
820
870
  except Exception as e:
821
871
  print(f"{Fore.RED} Error running test cases: {e}")
822
872
  return False