1919
2020# noinspection PyAttributeOutsideInit
2121class Nse :
22+ version : str = '3.7'
23+
2224 def __init__ (self , window : Tk ) -> None :
2325 self .intervals : List [int ] = [1 , 2 , 3 , 5 , 10 , 15 ]
2426 self .stdout : TextIO = sys .stdout
@@ -55,6 +57,31 @@ def get_icon_path() -> str:
5557 base_path = os .path .abspath ("." )
5658 return os .path .join (base_path , 'nse_logo.ico' )
5759
60+ def check_for_updates (self , auto : bool = True ) -> None :
61+ release_data : requests .Response = requests .get (
62+ "https://api.github.com/repos/VarunS2002/Python-NSE-Option-Chain-Analyzer/releases/latest" )
63+ latest_version : str = release_data .json ()['tag_name' ]
64+
65+ if float (latest_version ) > float (Nse .version ):
66+ self .info .attributes ('-topmost' , False ) if not auto else None
67+ update : bool = messagebox .askyesno (
68+ title = "New Update Available" ,
69+ message = f"You are running version: { Nse .version } \n "
70+ f"Latest version: { latest_version } \n "
71+ f"Do you want to update now ?\n "
72+ f"{ 'You can disable auto check for updates from the menu.' if auto and self .update else '' } " )
73+ if update :
74+ webbrowser .open_new ("https://github.com/VarunS2002/Python-NSE-Option-Chain-Analyzer/releases/latest" )
75+ self .info .attributes ('-topmost' , False ) if not auto else None
76+ else :
77+ self .info .attributes ('-topmost' , True ) if not auto else None
78+ else :
79+ if not auto :
80+ self .info .attributes ('-topmost' , False )
81+ messagebox .showinfo (title = "No Updates Available" , message = f"You are running the latest version.\n "
82+ f"Version: { Nse .version } " )
83+ self .info .attributes ('-topmost' , True )
84+
5885 def create_config (self , corrupted : bool = False ) -> None :
5986 if corrupted :
6087 os .remove ('NSE-OCA.ini' )
@@ -67,6 +94,7 @@ def create_config(self, corrupted: bool = False) -> None:
6794 self .config_parser .set ('main' , 'live_export' , 'False' )
6895 self .config_parser .set ('main' , 'notifications' , 'False' )
6996 self .config_parser .set ('main' , 'auto_stop' , 'False' )
97+ self .config_parser .set ('main' , 'update' , 'True' )
7098 self .config_parser .set ('main' , 'logging' , 'False' )
7199
72100 with open ('NSE-OCA.ini' , 'w' ) as f :
@@ -80,6 +108,7 @@ def get_config(self) -> None:
80108 self .live_export : bool = self .config_parser .getboolean ('main' , 'live_export' )
81109 self .notifications : bool = self .config_parser .getboolean ('main' , 'notifications' )
82110 self .auto_stop : bool = self .config_parser .getboolean ('main' , 'auto_stop' )
111+ self .update : bool = self .config_parser .getboolean ('main' , 'update' )
83112 self .logging : bool = self .config_parser .getboolean ('main' , 'logging' )
84113 except (configparser .NoOptionError , configparser .NoSectionError , configparser .MissingSectionHeaderError ,
85114 configparser .DuplicateSectionError , configparser .DuplicateOptionError ) as err :
@@ -386,6 +415,23 @@ def toggle_auto_stop(self, event: Optional[Event] = None) -> None:
386415 with open ('NSE-OCA.ini' , 'w' ) as f :
387416 self .config_parser .write (f )
388417
418+ # noinspection PyUnusedLocal
419+ def toggle_updates (self , event : Optional [Event ] = None ) -> None :
420+ if self .update :
421+ self .update = False
422+ self .options .entryconfig (self .options .index (6 ), label = "Auto Check for Updates: Off" )
423+ messagebox .showinfo (title = "Auto Checking for Updates Disabled" ,
424+ message = "Program will not check for updates at start." )
425+ else :
426+ self .update = True
427+ self .options .entryconfig (self .options .index (6 ), label = "Auto Check for Updates: On" )
428+ messagebox .showinfo (title = "Auto Checking for Updates Enabled" ,
429+ message = "Program will check for updates at start." )
430+
431+ self .config_parser .set ('main' , 'update' , f'{ self .update } ' )
432+ with open ('NSE-OCA.ini' , 'w' ) as f :
433+ self .config_parser .write (f )
434+
389435 # noinspection PyUnusedLocal
390436 def log (self , event : Optional [Event ] = None ) -> None :
391437 if self .first_run and self .logging or not self .logging :
@@ -402,7 +448,7 @@ def log(self, event: Optional[Event] = None) -> None:
402448 print ('.py version' )
403449
404450 try :
405- self .options .entryconfig (self .options .index (6 ), label = "Debug Logging: On" )
451+ self .options .entryconfig (self .options .index (7 ), label = "Debug Logging: On" )
406452 messagebox .showinfo (title = "Debug Logging Enabled" ,
407453 message = "Errors will be logged to NSE-OCA.log." )
408454 except AttributeError :
@@ -413,7 +459,7 @@ def log(self, event: Optional[Event] = None) -> None:
413459 sys .stderr = self .stderr
414460 streamtologger ._is_redirected = False
415461 self .logging = False
416- self .options .entryconfig (self .options .index (6 ), label = "Debug Logging: Off" )
462+ self .options .entryconfig (self .options .index (7 ), label = "Debug Logging: Off" )
417463 messagebox .showinfo (title = "Debug Logging Disabled" , message = "Errors will not be logged." )
418464
419465 self .config_parser .set ('main' , 'logging' , f'{ self .logging } ' )
@@ -468,7 +514,7 @@ def about(self, event: Optional[Event] = None) -> None:
468514 heading .grid (row = 0 , column = 0 , columnspan = 2 , sticky = N + S + W + E )
469515 version_label : Label = Label (self .info , text = "Version:" , relief = RIDGE )
470516 version_label .grid (row = 1 , column = 0 , sticky = N + S + W + E )
471- version_val : Label = Label (self .info , text = "3.7 " , relief = RIDGE )
517+ version_val : Label = Label (self .info , text = f" { Nse . version } " , relief = RIDGE )
472518 version_val .grid (row = 1 , column = 1 , sticky = N + S + W + E )
473519 dev_label : Label = Label (self .info , text = "Developer:" , relief = RIDGE )
474520 dev_label .grid (row = 2 , column = 0 , sticky = N + S + W + E )
@@ -487,7 +533,9 @@ def about(self, event: Optional[Event] = None) -> None:
487533 sources : Label = Label (self .info , text = "Sources" , fg = "blue" , cursor = "hand2" , relief = RIDGE )
488534 sources .bind ("<Button-1>" , lambda click , link = "sources" : self .links (link , click ))
489535 sources .grid (row = 4 , column = 1 , sticky = N + S + W + E )
490-
536+ updates : Button = Button (self .info , text = "Check for Updates" ,
537+ command = lambda auto = False : self .check_for_updates (auto ))
538+ updates .grid (row = 5 , column = 0 , columnspan = 2 , sticky = N + S + W + E )
491539 self .info .mainloop ()
492540
493541 # noinspection PyUnusedLocal
@@ -528,6 +576,8 @@ def main_win(self) -> None:
528576 self .options .add_command (label = f"Stop automatically at 3:30pm: { 'On' if self .auto_stop else 'Off' } " ,
529577 accelerator = "(Ctrl+K)" , command = self .toggle_auto_stop )
530578 self .options .add_separator ()
579+ self .options .add_command (label = f"Auto Check for Updates: { 'On' if self .update else 'Off' } " ,
580+ accelerator = "(Ctrl+U)" , command = self .toggle_updates )
531581 self .options .add_command (label = f"Debug Logging: { 'On' if self .logging else 'Off' } " , accelerator = "(Ctrl+L)" ,
532582 command = self .log )
533583 self .options .add_command (label = "About" , accelerator = "(Ctrl+M)" , command = self .about )
@@ -540,6 +590,7 @@ def main_win(self) -> None:
540590 self .root .bind ('<Control-b>' , self .toggle_live_export )
541591 self .root .bind ('<Control-n>' , self .toggle_notifications )
542592 self .root .bind ('<Control-k>' , self .toggle_auto_stop )
593+ self .root .bind ('<Control-u>' , self .toggle_updates )
543594 self .root .bind ('<Control-l>' , self .log )
544595 self .root .bind ('<Control-m>' , self .about )
545596 self .root .bind ('<Control-q>' , self .close )
@@ -1094,6 +1145,8 @@ def main(self) -> None:
10941145 self .set_values ()
10951146
10961147 if self .first_run :
1148+ if self .update :
1149+ self .check_for_updates ()
10971150 self .first_run = False
10981151 if self .str_current_time == '15:30:00' and not self .stop and self .auto_stop :
10991152 self .stop = True
0 commit comments