diff --git a/Changelog b/Changelog index c9c7779..722b4a0 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,19 @@ +2024-08-30 s-n-g + * version 0.9.3.10 + * do not enable xdg compliant if user_config_dir is specified + * do not create the default recording directory until it is + actually needed (to save data in it) + * when saving players' extra parameters reduce the list by removing + the unused porifles from the list + * Fixing player_params_file and schedule_file location when XDG + compliance is ON + * fixing a pyradio-client crash when no command is specified + * fixing: MPV Volume resets to 0% when trying to increase + beyond maximum #251 + * fixing a help crash: adding H_CONFIG_PLAYER help key + * added a gruvbox variation system theme + * updating docs and fixing broken links + 2024-06-04 s-n-g * version 0.9.3.9 * fixing a crash when adding a station to favorites diff --git a/docs/index.html b/docs/index.html index f82b188..ed36c40 100644 --- a/docs/index.html +++ b/docs/index.html @@ -215,6 +215,22 @@

Requirements Changelog Top

 
+2024-08-30 s-n-g
+    * version 0.9.3.10
+    * do not enable xdg compliant if user_config_dir is specified
+    * do not create the default recording directory until it is
+      actually needed (to save data in it)
+    * when saving players' extra parameters reduce the list by removing
+      the unused porifles from the list
+    * Fixing player_params_file and schedule_file location when XDG
+      compliance is ON
+    * fixing a pyradio-client crash when no command is specified
+    * fixing: MPV Volume resets to 0% when trying to increase
+      beyond maximum #251
+    * fixing a help crash: adding H_CONFIG_PLAYER help key
+    * added a gruvbox variation system theme
+    * updating docs and fixing broken links
+
 2024-06-04 s-n-g
     * version 0.9.3.9
     * fixing a crash when adding a station to favorites
diff --git a/docs/pyradio.1 b/docs/pyradio.1
index 355fff8..8f7acae 100644
--- a/docs/pyradio.1
+++ b/docs/pyradio.1
@@ -1220,8 +1220,8 @@ Two themes by \fBedunfelt\fR (\fIhttps://github.com/edunfelt\fR) inspired by the
 .IP \fBdracula_by_Plyply99\fR
 A theme based of the Dracula theme by \fBPlyply99\fR (\fIhttps://github.com/Plyply99\fR).
 
-.IP \fBgruvbox_dark_by_sng\fR\ and\ \fBgruvbox_light_by_sng\fR
-Two themes based on the \fBgruvbox\fR (\fIhttps://github.com/morhetz/gruvbox\fR) theme.
+.IP \fBgruvbox_dark_by_farparticul\fR,\ \fBgruvbox_dark_by_sng\fR\ and\ \fBgruvbox_light_by_sng\fR
+Three themes based on the \fBgruvbox\fR (\fIhttps://github.com/morhetz/gruvbox\fR) theme.
 
 .IP \fBhyprland_amber_gold\fR\ and\ \fBhyprland_dracula\fR
 Two themes by \fBmechatour\fR (\fIhttps://github.com/mechatour\fR), from \fBhyprland_amber_gold\fR (\fIhttps://github.com/mechatour/hyprland_amber_gold\fR) and \fBhyprland_dotfiles\fR (\fI[https://github.com/mechatour/hyprland_dotfiles\fR).
diff --git a/docs/rec-dir.html b/docs/rec-dir.html
index 4a68564..616a124 100644
--- a/docs/rec-dir.html
+++ b/docs/rec-dir.html
@@ -87,5 +87,15 @@ 

Pre 0.9.3 installation behavior Pre 0.9.3 installations will use ~/.config/pyradio/data/recordings as the recording directory, by default.

After updating to v. 0.9.3 (and newer), PyRadio will move this directory to the user’s home folder and rename it to “pyradio-recordings”.

Then the user can change the folder’s location from Config / General options / Recording dir.

+

Post 0.9.3.10 behavior Top

+

Up until v. 0.9.3.10, Ryradio would create the “recording directory” upon startup, no matter where it would be located, making it available for the recording and titles’ log function.

+

This eventually creates the following problem:

+

A user who never wants to use the recording or the titles’ log function, ends up with an empty directory in his home folder, which will be recreated every time PyRadio is executed (even if deleted before that), as described in issue No. 253.

+

The solution is that PyRadio will remove the “recording directory” upon execution, if

+
    +
  1. the default location is used
  2. +
  3. the directory is empty
  4. +
+

As a consequence, both the recording and the titles’ log function will make sure the directory actually exists (and create it if it does not), before trying to save any data to it.

diff --git a/docs/rec-dir.md b/docs/rec-dir.md index bfd4e63..32c0564 100644 --- a/docs/rec-dir.md +++ b/docs/rec-dir.md @@ -39,3 +39,17 @@ After updating to v. 0.9.3 (and newer), **PyRadio** will move this directory to Then the user can change the folder's location from *Config / General options / Recording dir*. +## Post 0.9.3.10 behavior + +Up until **v. 0.9.3.10, Ryradio** would create the "*recording directory*" upon startup, no matter where it would be located, making it available for the recording and titles' log function. + +This eventually creates the following problem: + +A user who never wants to use the recording or the titles' log function, ends up with an empty directory in his home folder, which will be recreated every time **PyRadio** is executed (even if deleted before that), as described in [issue No. 253](https://github.com/coderholic/pyradio/issues/253). + +The solution is that **PyRadio** will remove the "*recording directory*" upon execution, if + +1. the default location is used +2. the directory is empty + +As a consequence, both the recording and the titles' log function will make sure the directory actually exists (and create it if it does not), before trying to save any data to it. diff --git a/docs/themes.html b/docs/themes.html index 6622136..6b34751 100644 --- a/docs/themes.html +++ b/docs/themes.html @@ -45,7 +45,10 @@

Table of Contents <
  • PyRadio Themes
      -
    • Virtual terminal restrictions
    • +
    • Virtual terminal restrictions +
    • CSS color themes restrictions
    • Secondary windows background
        @@ -108,8 +111,8 @@

        PyRadio Themes edunfelt inspired by the base16 project.
      • dracula_by_Plyply99
        A theme based of the Dracula theme by Plyply99.
      • -
      • gruvbox_dark_by_sng and gruvbox_light_by_sng
        -Two themes based on the gruvbox theme.
      • +
      • gruvbox_dark_by_farparticul, gruvbox_dark_by_sng and gruvbox_light_by_sng
        +Three themes based on the gruvbox theme.
      • hyprland_amber_gold and hyprland_dracula
        Two themes by mechatour, from hyprland_amber_gold and hyprland_dotfiles.
      • minima_by_ben_chile
        @@ -180,6 +183,12 @@

        Virtual terminal restrictions

        PyRadio will try to detect these terminals and disable themes (after displaying a relative message). Then the default theme will be used.

        Some of the terminals that work ok, are: gnome-terminal, mate-terminal, xfce4-terminal, lxterminal, terminator, termite, kitty, alacritty, sakura, roxterm, tilix, lilyterm, st, xst, rxvt, urxvt, uxterm, xterm.

        If you want to make PyRadio start in one of these terminal, just follow the instructions given at Desktop File: Specifying the terminal to use.

        +

        Workaround for not supported terminals

        +

        Thanks to github user troyvit, it is now possible to use PyRadio with full color support on most of the terminals that originally will not display colors correctly.

        +

        Following his report, which proposes to execute PyRadio within a tmux session, a bash srciprt has been written to accomplish the task: it is called “tmux_pyradio” and comes in the form of a github gist.

        +

        Using “tmux_pyradio” on can execute PyRadio in any terminal (it has been tested in all the terminals referenced above); one can even run a second PyRadio instance throught it. For more info, download it and execute:

        +
        tmux_pyradio -h
        +

        There is a catch though; if PyRadio terminates prematurely, the output will not be visible to the user, since tmux will also terminate and clear the screen on exit. In this case, just add a “-d” before a “” (or combine it with the custom tmux session name). Yhis will add a pause before exiting tmux, so you can observe the output.

        CSS color themes restrictions

        Using CSS colors imposes a couple of restrictions on the type of terminals PyRadio will be able to run:

          diff --git a/docs/themes.md b/docs/themes.md index abaa9e6..6687a1b 100644 --- a/docs/themes.md +++ b/docs/themes.md @@ -5,6 +5,7 @@ * [PyRadio Themes](#pyradio-themes) * [Virtual terminal restrictions](#virtual-terminal-restrictions) + * [Workaround for not supported terminals](#workaround-for-not-supported-terminals) * [CSS color themes restrictions](#css-color-themes-restrictions) * [Secondary windows background](#secondary-windows-background) * [Theme defined secondary windows color](#theme-defined-secondary-windows-color) @@ -57,8 +58,8 @@ A clasic theme by [The OpenBSD Guy](https://github.com/OpenBSDGuy), originally c Two themes by [edunfelt](https://github.com/edunfelt) inspired by the [base16](https://github.com/base16-project) project. - **dracula_by_Plyply99** \ A theme based of the Dracula theme by [Plyply99](https://github.com/Plyply99). -- **gruvbox_dark_by_sng** and **gruvbox_light_by_sng** \ -Two themes based on the [gruvbox](https://github.com/morhetz/gruvbox) theme. +- *gruvbox_dark_by_farparticul*, **gruvbox_dark_by_sng** and **gruvbox_light_by_sng** \ +Three themes based on the [gruvbox](https://github.com/morhetz/gruvbox) theme. - **hyprland_amber_gold** and **hyprland_dracula** \ Two themes by [mechatour](https://github.com/mechatour), from [hyprland_amber_gold](https://github.com/mechatour/hyprland_amber_gold) and [hyprland_dotfiles]([https://github.com/mechatour/hyprland_dotfiles). - **minima_by_ben_chile** \ @@ -146,6 +147,18 @@ Some of the terminals that work ok, are: *gnome-terminal*, *mate-terminal*, *xfc If you want to make **PyRadio** start in one of these terminal, just follow the instructions given at [Desktop File: Specifying the terminal to use](#specifying-the-terminal-to-use). +#### Workaround for not supported terminals + +Thanks to github user [troyvit](https://github.com/troyvit), it is now possible to use **PyRadio** with full color support on most of the terminals that originally will not display colors correctly. + +Following his [report](https://github.com/coderholic/pyradio/issues/254), which proposes to execute **PyRadio** within a [tmux](https://github.com/tmux/tmux/wiki) session, a [bash srciprt](https://gist.github.com/s-n-g/2f1ef5c764222d26e5bb0075b2adddb1) has been written to accomplish the task: it is called "**tmux_pyradio**" and comes in the form of a github gist. + +Using "**tmux_pyradio**" on can execute **PyRadio** in any terminal (it has been tested in all the terminals referenced above); one can even run a second **PyRadio** instance throught it. For more info, download it and execute: + + tmux_pyradio -h + +There is a catch though; if **PyRadio** terminates prematurely, the output will not be visible to the user, since **tmux** will also terminate and clear the screen on exit. In this case, just add a "*-d*" before a "*--*" (or combine it with the custom tmux session name). Yhis will add a *pause* before exiting **tmux**, so you can observe the output. + ### CSS color themes restrictions Using CSS colors imposes a couple of restrictions on the type of terminals **PyRadio** will be able to run: diff --git a/pyproject.toml b/pyproject.toml index 777105d..7fac9e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pyradio" -version = "0.9.3.9" +version = "0.9.3.10" authors = [ { name="Ben Dowling", email="ben.m.dowling@gmail.com" }, { name="Spiros Georgaras", email="sng@hellug.gr" }, diff --git a/pyradio/__init__.py b/pyradio/__init__.py index 8266b68..5f35e06 100644 --- a/pyradio/__init__.py +++ b/pyradio/__init__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- " pyradio -- Console radio player. " -version_info = (0, 9, 3, 9) +version_info = (0, 9, 3, 10) # Set it to True if new stations have been # added to the package's stations.csv diff --git a/pyradio/config.py b/pyradio/config.py index 0f304fa..3565c80 100644 --- a/pyradio/config.py +++ b/pyradio/config.py @@ -2420,23 +2420,25 @@ def _read_config(self, distro_config=False): except: pass self._first_read = False - logger.error('\n\nfile = {0}\nplayer extra params = {1}\n\n'.format(self.player_params_file, self.params)) + # logger.error('\n\nfile = {0}\nplayer extra params = {1}\n\n'.format(self.player_params_file, self.params)) # do this here to get proper schedule config filepath if XDG is on self.schedule_file = path.join(self.data_dir, 'schedule.json') def _make_sure_dirs_exist(self): + home_rec_dir = path.join(path.expanduser('~'), 'pyradio-recordings') if self.opts['recording_dir'][1] == '': self.opts['recording_dir'][1] = path.join(path.expanduser('~'), 'pyradio-recordings') ch_dir = CheckDir( self.opts['recording_dir'][1], - path.join(path.expanduser('~'), 'pyradio-recordings') + home_rec_dir, + remove_after_validation=True ) - if not ch_dir.is_dir: + if not ch_dir.can_be_created: print('Error: Recordings directory is for a folder: "{}"'.format(self.opts['recording_dir'][1])) sys.exit(1) - elif not ch_dir.is_writable: + elif not ch_dir.can_be_writable: print('Error: Recordings directory is not writable: "{}"'.format(self.opts['recording_dir'][1])) sys.exit(1) @@ -2462,6 +2464,12 @@ def _make_sure_dirs_exist(self): first_read=path.join(self.stations_dir, 'data', 'recordings') ) + # remove recordings dir from home dir if it is empty, as per #253 + if path.exists(self.opts['recording_dir'][1]) and \ + self.opts['recording_dir'][1] == home_rec_dir and \ + len(listdir(self.opts['recording_dir'][1])) == 0: + remove_tree(self.opts['recording_dir'][1]) + def get_last_playlist(self): ''' read last opened playlist reads: ~/pyradio/last_playlist @@ -3360,24 +3368,37 @@ def configure_logger(self, recording_dir=None, debug=None, titles=None): self.log_degub = True if titles and not self.log_titles: - logger.error('setting up pyradio-titles.py') - self.titles_handler = logging.handlers.RotatingFileHandler( - path.join( - recording_dir, - 'pyradio-titles.log'), - maxBytes=50000, - backupCount=5) - self.titles_handler.setFormatter(logging.Formatter( - fmt=self.PATTERN_TITLE, - datefmt='%b %d (%a) %H:%M') - ) - self.titles_handler.setLevel(logging.CRITICAL) - #l = logging.getLogger() - logger.addHandler(self.titles_handler) - self.log_titles = True - logger.critical('=== Logging started') if logger.isEnabledFor(logging.INFO): - logger.info('starting titles logg on: "{}"'.format(recording_dir)) + logger.info('setting up pyradio-titles.log') + if not path.exists(recording_dir): + try: + makedirs(recording_dir) + except: + pass + if not path.exists(recording_dir): + self.log_titles = False + self.titles_handler = None + if logger.isEnabledFor(logging.ERROR): + logger.error('cannot start titles log on: "{}"; directory does not exist'.format(recording_dir)) + return False + else: + self.titles_handler = logging.handlers.RotatingFileHandler( + path.join( + recording_dir, + 'pyradio-titles.log'), + maxBytes=50000, + backupCount=5) + self.titles_handler.setFormatter(logging.Formatter( + fmt=self.PATTERN_TITLE, + datefmt='%b %d (%a) %H:%M') + ) + self.titles_handler.setLevel(logging.CRITICAL) + #l = logging.getLogger() + logger.addHandler(self.titles_handler) + self.log_titles = True + logger.critical('=== Logging started') + if logger.isEnabledFor(logging.INFO): + logger.info('starting titles log on: "{}"'.format(recording_dir)) if (not titles) and self.log_titles: if self.titles_handler: @@ -3389,6 +3410,7 @@ def configure_logger(self, recording_dir=None, debug=None, titles=None): logging.raiseExceptions = False logging.lastResort = None # logger.info('self.log_titles = {}'.format(self.log_titles)) + return True def tag_title(self, the_log): ''' tags a title diff --git a/pyradio/install.py b/pyradio/install.py index d1709c7..6090399 100644 --- a/pyradio/install.py +++ b/pyradio/install.py @@ -16,7 +16,7 @@ ''' This is PyRadio version this install.py was released for ''' -PyRadioInstallPyReleaseVersion = '0.9.3.9' +PyRadioInstallPyReleaseVersion = '0.9.3.10' import locale locale.setlocale(locale.LC_ALL, "") diff --git a/pyradio/player.py b/pyradio/player.py index 893cc7f..deee37c 100644 --- a/pyradio/player.py +++ b/pyradio/player.py @@ -2030,6 +2030,7 @@ def play(self, logger.info('Executing command: {}'.format(' '.join(opts))) except: pass + if platform.startswith('win') and self.PLAYER_NAME == 'vlc': self.stop_win_vlc_status_update_thread = False ''' Launches vlc windowless ''' diff --git a/pyradio/radio.py b/pyradio/radio.py index 33cfa14..e22e714 100644 --- a/pyradio/radio.py +++ b/pyradio/radio.py @@ -490,13 +490,13 @@ def __init__(self, pyradio_config, '/html_next': self._html_play_next_station, '/stop': self._stop_player, '/html_stop': self._html_stop_player, - '/start': self._start_player, + '/start': self._text_start_player, '/html_start': self._html_start_player, '/jump': self._jump_and_play_selection, 'open_history': self._open_playlist_and_station_from_station_history, - '/log': self._toggle_titles_logging, + '/log': self._text_toggle_titles_logging, '/html_log': self._html_toggle_titles_logging, - '/like': self._tag_a_title, + '/like': self._text_tag_a_title, '/html_like': self._html_tag_a_title, '/title': self._html_song_title, '/html_info': self._html_info, @@ -5674,8 +5674,18 @@ def _can_show_theme_window_in_browser_search(self): else: return True + def _text_toggle_titles_logging(self): + if not self.toggle_titles_logging(): + return 'Error: Recording dir does not exist!' + self.log.write_start_log_station_and_title() + if self._cnf.titles_log.titles_handler: + return 'Titles Logging Enabled' + else: + return 'Titles Logging Disabled' + def _html_toggle_titles_logging(self): - self.toggle_titles_logging() + if not self.toggle_titles_logging(): + return '
          Error!
          Recording dir does not exist!
          ' self.log.write_start_log_station_and_title() if self._cnf.titles_log.titles_handler: return '
          Title Log Enabled
          ' @@ -5683,19 +5693,45 @@ def _html_toggle_titles_logging(self): return '
          Title Log Disabled
          ' def _toggle_titles_logging(self): - self.toggle_titles_logging() - self.log.write_start_log_station_and_title() - if self._cnf.titles_log.titles_handler: - self._show_delayed_notification('___Title Log Enabled___') + if self.toggle_titles_logging(): + self.log.write_start_log_station_and_title() + if self._cnf.titles_log.titles_handler: + self._show_delayed_notification('___Titles Log Enabled___') + else: + self._show_delayed_notification('___Titles Log Disabled___') else: - self._show_delayed_notification('___Title Log Disabled___') + self._show_delayed_notification( + '___|Error|: Recording dir does |not exist|!___', + delay=1.5 + ) + + def _text_tag_a_title(self): + return self._tag_a_title(text=True) def _html_tag_a_title(self): return self._tag_a_title(html=True) - def _tag_a_title(self, html=False): + def _tag_a_title(self, html=False, text=False): if self.player.isPlaying(): if self._cnf.can_like_a_station(): + if not path.exists(self._cnf.recording_dir): + try: + makedirs(self._cnf.recording_dir) + except: + pass + if not path.exists(self._cnf.recording_dir): + if logger.isEnabledFor(logging.ERROR): + logger.error('cannot like title; directory "{}" does not exist'.format(self._cnf.recording_dir)) + if text: + return 'Error: Recodring dir does not exist!' + elif html: + return '
          Error!
          Recording dir does not exist!
          ' + else: + self._show_delayed_notification( + '___|Error|: Recording dir does |not exist|!___', + delay=1.5 + ) + return toggled = False if self._cnf.titles_log.titles_handler is None: self.toggle_titles_logging() @@ -5707,22 +5743,30 @@ def _tag_a_title(self, html=False): else: ret = 2 if ret == 0: - if html: + if text: + return 'Title tagged as liked!' + elif html: return '
          Title tagged as liked!
          ' else: self._show_delayed_notification('___Title tagged as liked___') elif ret == 1: - if html: + if text: + return 'Error liking Title' + elif html: return '
          Error liking Title
          ' else: self._show_delayed_notification('___Error liking Title___', delay=1.2) else: - if html: + if text: + return 'Title already tagged as liked!' + elif html: return '
          Title already tagged as liked!
          ' else: self._show_delayed_notification('___Title already tagged as liked___') else: - if html: + if text: + return 'Player is stopped!' + elif html: return '
          Player is stopped!
          ' else: self._show_delayed_notification('___Error: Player not in playback___', delay=1.2) @@ -9118,17 +9162,59 @@ def _jump_to_jumpnr(self, char='', jumpnr=None): self._put_selection_in_the_middle(force=force_center) self.jumpnr = '' + def _return_server_response_for_start_player(self, mode=None): + if self.player.recording > 0: + if not os.path.exists(self._cnf.recording_dir): + try: + os.makedirs(self._cnf.recording_dir) + except: + pass + if not os.path.exists(self._cnf.recording_dir): + if mode == 'text': + return 'Error: Recording not available; Recording dir does not exist!' + elif mode == 'html': + return '
          Error!
          Recording not available!
          Recording dir does not exist!
          ' + return None + + def _text_start_player(self): + self._reset_status_bar_right() + ret = self._html_check_op_mode() + if ret is not None: + return ret + if self._return_server_response_for_start_player(mode='text'): + return ret + if self.number_of_items > 0: + self._start_player(mode='text') + return 'Playing "{}"!'.format(self.stations[self.selection][0]) + return 'No stations in Playlist!!' + def _html_start_player(self): self._reset_status_bar_right() ret = self._html_check_op_mode() if ret is not None: return ret + if self._return_server_response_for_start_player(mode='text'): + return ret if self.number_of_items > 0: - self._start_player() + self._start_player(mode='html') return '
          Playing {}!
          '.format(self.stations[self.selection][0]) return '
          No stations in Playlist!!
          ' - def _start_player(self): + def _start_player(self, mode=None): + if self.player.recording > 0: + if not os.path.exists(self._cnf.recording_dir): + try: + makedirs(self._cnf.recording_dir) + except: + pass + if not os.path.exists(self._cnf.recording_dir): + if self._return_server_response_for_start_player(mode): + return ret + self._show_delayed_notification( + '___Recording |not| available!___\n_Recording dir does |not exist|!', + delay=1.5 + ) + return False self.player.already_playing = False self._reset_status_bar_right() # with self._buffering_lock: @@ -9138,6 +9224,7 @@ def _start_player(self): if self.number_of_items > 0: self.playSelection() self.refreshBody() + return True def _html_stop_player(self): self._reset_status_bar_right() @@ -10072,7 +10159,7 @@ def set_param_set_by_id(self, a_param_id=0): return True def toggle_titles_logging(self): - self._cnf.titles_log.configure_logger( + return self._cnf.titles_log.configure_logger( recording_dir=self._cnf.recording_dir, titles=not self._cnf.titles_log.log_titles ) diff --git a/pyradio/server.py b/pyradio/server.py index bdb77ea..18f52c6 100644 --- a/pyradio/server.py +++ b/pyradio/server.py @@ -937,8 +937,6 @@ class PyRadioServer(object): '/error': 'Error in parameter', '/perm': 'Operation not permitted (not in Main Mode)', '/perm_html': '
          Operation not permitted (not in Main Mode)
          ', - '/log': 'Stations logging toggled', - '/like': 'Station tagged (liked)', } def __init__(self, bind_ip, bind_port, config, player, commands): @@ -1157,8 +1155,8 @@ def _handle_client_connection(self, address, request): # logger.error('received = "{}"'.format(received)) self._send_raw(received) else: - self._commands['/log']() - self._send_text(self._text['/log']) + received = self._commands['/log']() + self._send_text(received) elif self._path in ('/like', '/l'): if self._is_html: @@ -1166,11 +1164,9 @@ def _handle_client_connection(self, address, request): # logger.error('received = "{}"'.format(received)) self._send_raw(received) else: - if self.sel()[1] > -1: - self._commands['/like']() - self._send_text(self._text['/like']) - else: - self._send_text(self._text['/idle']) + received = self._commands['/like']() + # logger.error('received = "{}"'.format(received)) + self._send_text(received) elif self._path in ('/mute', '/m'): if self._is_html: diff --git a/pyradio/xdg.py b/pyradio/xdg.py index 327a716..2bf6e95 100644 --- a/pyradio/xdg.py +++ b/pyradio/xdg.py @@ -670,6 +670,9 @@ def migrate_titles(self): class CheckDir(object): + _is_writable = False + _can_be_writable = False + _can_be_created = False def __init__(self, a_path, default=None, remove_after_validation=False): self._remove_after_validation = remove_after_validation @@ -682,6 +685,14 @@ def __init__(self, a_path, default=None, remove_after_validation=False): expanded_default = self._replace_tilde(default) self.dir_path = self._replace_tilde(expanded_default) + @property + def can_be_created(self): + return self._can_be_created + + @property + def can_be_writable(self): + return self._can_be_writable + @property def is_writable(self): return self._is_writable @@ -707,7 +718,9 @@ def _validate_path(self, a_path=None): a_path = self.dir_path # make sure path exists and is writable self._is_writable = False - if not path.exists(self.dir_path): + if path.exists(self.dir_path): + self._can_be_created = True + else: if system().lower() == 'windows': splited_path = self.dir_path.split(path.sep) existing = splited_path[0] @@ -725,8 +738,10 @@ def _validate_path(self, a_path=None): # it does not exist, try to create it try: makedirs(self.dir_path) + self._can_be_created = True created = True except: + self._can_be_created = False return False ret = False if path.isdir(self.dir_path): @@ -737,6 +752,7 @@ def _validate_path(self, a_path=None): pass remove(test_file) self._is_writable = True + self._can_be_writable = True ret = True except: pass