Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

file_status: allow several paths, new format #1369

Merged
merged 21 commits into from
Jul 5, 2018

Conversation

cyrinux
Copy link
Contributor

@cyrinux cyrinux commented Jun 9, 2018

I have a usecase where I want to check a path with wildcard, eg

file_status VPN {                                                                                                                                                                                                                         
  cache_timeout = -1
  path = '/proc/sys/net/ipv4/conf/tun-vpn*'
  format = 'vpn: UP'
 }

I want the test success if /proc/sys/net/ipv4/conf/tun-vpn1 or /proc/sys/net/ipv4/conf/tun-vpn2 is present for example.

Think this could be usefull.

@cyrinux cyrinux force-pushed the file_status-allow-glob branch from a932a69 to 1909b9e Compare June 9, 2018 21:12
@cyrinux cyrinux changed the title allow glob (wildcard *) in path params file_status: allow glob (wildcard *) in path params Jun 10, 2018
@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 12, 2018

@lasers you do you think about? Should I add in this PR the way to handle:
path = ['/path/1' '/path/2'] or path = '/path/1,/path/1'

Copy link
Contributor

@lasers lasers left a comment

Choose a reason for hiding this comment

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

path = ['/path/1' '/path/2'] or path = '/path/1,/path/1'

path = [] sounds good because it could allow us to specify multiple path all over the /, but probabl should convert path = '~/example' to path=[] in post_config_hook for backward compatibility.

glob is useful because we could catch files such as ~/modules/*.py plus {path} to print a list of test modules in the bar. :-) P.S. I'd clear this with the fam first.

def post_config_hook(self):
if self.path:
self.path = expanduser(self.path)

Copy link
Contributor

Choose a reason for hiding this comment

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

Keep this so we can do expanduser(path) once instead of every refresh interval.

Copy link
Contributor Author

@cyrinux cyrinux Jun 12, 2018

Choose a reason for hiding this comment

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

I had a doubt about this, refresh is for example when I py3-cmd resfresh file_status? I thought this part was only excecuted at the py3status start/restart.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not understand this sorry, could you rephrase? "I'd clear this with the fam first."

Copy link
Contributor

Choose a reason for hiding this comment

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

Have a discussion with tobes and/or ultrabug. They our fam.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh sorry, fam = familly >_>

color = self.py3.COLOR_BAD
paths = glob(expanduser(self.path))
if isinstance(paths, str):
paths = [paths]
Copy link
Contributor

Choose a reason for hiding this comment

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

When we glob stuffs, is paths not always a list? Also, to get rid of expanduser here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it is not always a list, if there is nothing to glob the return stay a str

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know what to make of this. Consult with the fam.

Copy link
Contributor Author

@cyrinux cyrinux Jun 12, 2018

Choose a reason for hiding this comment

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

weird, will retry

glob.glob(pathname, , recursive=False)
Return a possibly-empty list of path names that match pathname, which must be a string containing a path specification. pathname can be either absolute (like /usr/src/Python-1.5/Makefile) or relative (like ../../Tools/
/*.gif), and can contain shell-style wildcards. Broken symlinks are included in the results (as in the shell).

color = self.py3.COLOR_BAD

for path in paths:
if exists(path):
Copy link
Contributor

Choose a reason for hiding this comment

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

If we use glob, then we might not need exists anymore -- Try if paths: instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok for this :)

if exists(path):
icon = self.icon_available
color = self.py3.COLOR_GOOD
break

response = {
'cached_until': self.py3.time_in(self.cache_timeout),
Copy link
Contributor

Choose a reason for hiding this comment

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

cache_timeout = -1 in your example means once. You may want cache_timeout = 0 instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In my example I use py3-cmd refresh file_status for try ;)

@cyrinux cyrinux changed the title file_status: allow glob (wildcard *) in path params file_status: allow several path Jun 12, 2018
@cyrinux cyrinux force-pushed the file_status-allow-glob branch from 510e0cc to 769caaa Compare June 12, 2018 19:00
backward compat from str to list
handle glob wildcard
@cyrinux cyrinux force-pushed the file_status-allow-glob branch from 769caaa to bced76b Compare June 12, 2018 19:06
@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 12, 2018

@lasers, i hope it is better like this, I think i haven't miss test from my side. Works as I want.

@lasers
Copy link
Contributor

lasers commented Jun 13, 2018

Hi. I have a request. I want a {basename} placeholder. I guess to do this right, we would have format_path and format_path_separator. I don't know what would be in format_path, but I'm guessing at least {basename} and (full) {path}... Plz, a ham burger for you. 🍔

@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 13, 2018

I will do ;) I have forget this remark and was thinking of it at wakup ^^ Thanks for the 🍔

@cyrinux cyrinux force-pushed the file_status-allow-glob branch from c635711 to eec5c31 Compare June 13, 2018 06:46
Copy link
Contributor

@lasers lasers left a comment

Choose a reason for hiding this comment

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

Breaks on...

file_status {
    path = '~/.config/i3/modules/*.py'
}

@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 18, 2018

@lasers tell me more, what do you get?

@lasers
Copy link
Contributor

lasers commented Jun 18, 2018

I'm trying to understand this. It's weird. When I run path through test_module, python2 and python3 came out okay.... listing 5 modules or so... but on the bar, it's just displaying everything in $HOME. My bar gets overflowed with bunch of scrot screenshots and various files + directories.

EDIT: I tried same thing on different bar and got same result. This is anomaly. Idk why. Ouch. :-)

@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 18, 2018

Ouch. Running well here.
No problem from my side even with lots of files, like all my home dir + py3status modules dir.
Could you tell more on the process to try to reproduce same thing plz?

@lasers
Copy link
Contributor

lasers commented Jun 18, 2018

The fix is

diff --git a/py3status/modules/file_status.py b/py3status/modules/file_status.py
index 91a5ef68..103f6edc 100644
--- a/py3status/modules/file_status.py
+++ b/py3status/modules/file_status.py
@@ -47,6 +47,11 @@ from os.path import basename, expanduser
 
 ERR_NO_PATH = 'no path given'
 
+try:
+    basestring
+except NameError:
+    basestring = str
+
 
 class Py3status:
     """
@@ -79,7 +84,7 @@ class Py3status:
     def post_config_hook(self):
         if self.path:
             # backward compatibility, str to list
-            if isinstance(self.path, str):
+            if isinstance(self.path, basestring):
                 self.path = [self.path]
             # expand user paths
             self.path = list(map(expanduser, self.path))

@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 18, 2018

Is it due to python version? Thanks.

@lasers
Copy link
Contributor

lasers commented Jun 18, 2018

Yup. Debian runs Python 2.7.13 here. I wonder if we have more of those isinstance(string, str) in other modules and if they really worked okay. This also seems unrelated to --gevent.

I don't know why we didn't catch this before... but I think it was because we never had to use instance(string, str) for most things so maybe this was the first time. You can avoid try/except lines too by testing for a (not) list instead. Cheers.

EDIT: Okay... No other modules. Just i3py3status.py. Python2 is not supported there.

./i3pystatus.py:151:                if isinstance(callback, str):

# expand glob from paths
paths = list(map(glob, self.path))
# merge list of paths
paths = [x for x in chain.from_iterable(paths)]
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it is more efficient to += the list instead of using chain and map.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Idk

Copy link
Contributor

Choose a reason for hiding this comment

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

Try paths = sorted([files for path in self.path for files in glob(path)])

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Dont know if this is better but it works :) not used to read this :|

color = self.py3.COLOR_BAD

if paths:
file_status_data['icon'] = self.icon_available
Copy link
Contributor

Choose a reason for hiding this comment

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

Here, I really would like to deprecate icon in favor of a files (like message/messages) so the format could look like this... format = '\?if=files ●|■' instead... And {files} would be a number of files.

I guess we stick with just allow several path and not rewriting this from scratch. lol.

Just mentioning that file_status will pick up directories too with wildcard. Anyhow, keep it as-is.

Copy link
Contributor Author

@cyrinux cyrinux Jun 18, 2018

Choose a reason for hiding this comment

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

So i remove legacy stuff? Or I just add files, and we can remove {icon} from config and use new format.

Copy link
Contributor

@lasers lasers Jun 18, 2018

Choose a reason for hiding this comment

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

Ideally, we do no more than to allow several path PR. We definitely can add (count) {paths} for format because it is still related.

It'd be good to ask the fam first about deprecating {icon} as this would allow us to get rid of icon_available and icon_unavailable in favor of format = '\?if=paths ●|■'. Also, ask about the new {format_path} in default format (versus) just icons. I think it's better than icons too. Maybe not...

format_path['basename'] = self.py3.composite_join(
format_path_separator, map(basename, paths))

format_path['full'] = self.py3.composite_join(
Copy link
Contributor

Choose a reason for hiding this comment

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

Due to glob, there can be many things in the list. We could be a bit more efficient by using get_placeholders_list-in-post_config_hook list for format_path and find out which placeholder we want to join... rather than always joining them both.

Look composite_join in composite.py. It makes a composite obj, go thru list, append separator, append item, etc... which could always be skipped on every interval instead. This is an optional nit.

@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 18, 2018

@lasers, i have try to implement what you say, not sure to successfully done them all.

@lasers
Copy link
Contributor

lasers commented Jun 18, 2018

Friendly ping: @tobes, @ultrabug... When are you coming home? I have been holding down the
fort here.

@cyrinux I'll have a look.

Copy link
Contributor

@lasers lasers left a comment

Choose a reason for hiding this comment

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

Here's what I'm thinking right now... The new format can affect the existing users, but it could bring in more users too because now users can just glob files and have it appearing in the bar... That part sounds so much better than seeing a vague icon.

if self.path:
# backward compatibility, str to list
if not isinstance(self.path, list):
self.path = [self.path]
# expand user paths
self.path = list(map(expanduser, self.path))

self.format_path_separator = self.py3.safe_format(self.format_path_separator)
Copy link
Contributor

@lasers lasers Jun 18, 2018

Choose a reason for hiding this comment

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

Smart move. I did that before. However, the problem is that this won't work with thresholds, eg '\?color=paths ,' to follow number of paths or such. It's not likely to happen here, but could happen in other modules so we keep them in the main.... EDIT: not for colors, but for other formatters too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, i reput it in the main so

@@ -98,30 +104,33 @@ def file_status(self):
paths = list(map(glob, self.path))
# merge list of paths
paths = [x for x in chain.from_iterable(paths)]
file_status_data['files'] = len(paths)
Copy link
Contributor

Choose a reason for hiding this comment

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

paths is better. More explicit and the fact that this can pick up directories too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup

format_path_separator, paths)
for x in self.placeholders:
format_path[x] = self.py3.composite_join(
self.format_path_separator, format_path[x]
Copy link
Contributor

Choose a reason for hiding this comment

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

The code here looks great. The set() stuffs above is not great and should be done in post_config_hook instead similar to wwan.py.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok

@cyrinux cyrinux force-pushed the file_status-allow-glob branch from 35b68d1 to 08b7481 Compare June 19, 2018 08:15
Copy link
Contributor

@lasers lasers left a comment

Choose a reason for hiding this comment

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

Nice. Almost done. 👊

@@ -68,17 +111,40 @@ def file_status(self):
'cached_until': self.py3.CACHE_FOREVER,
Copy link
Contributor

Choose a reason for hiding this comment

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

We should move this to post_config_hook too. See hamster for an example.

Copy link
Contributor Author

@cyrinux cyrinux Jun 19, 2018

Choose a reason for hiding this comment

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

hamster from which branch? :)

Copy link
Contributor

@lasers lasers Jun 19, 2018

Choose a reason for hiding this comment

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

Master Splinter! Or see weather_yahoo.. or to be more specific, do like this...

STRING_NO_PATH = 'missing path'
    def post_config_hook(self):
        if not self.path:
            raise Exception(STRING_NO_PATH)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ha ok I was far away


# get thresholds
if self.thresholds:
self.py3.threshold_get_color(paths_number, 'paths')
Copy link
Contributor

Choose a reason for hiding this comment

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

(Request) Move this down right before the return (traditionally left at bottom for looping or such).

self.py3.safe_format(self.format, {
'paths': paths_number,
'format_path': format_path
})
Copy link
Contributor

Choose a reason for hiding this comment

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

(Request) An attempt on creating consistency in all modules and could be a project's coding style if we were to document it... to make it more readability or such.

        return {
            'cached_until': self.py3.time_in(self.cache_timeout),
            'full_text': self.py3.safe_format(
                self.format, {
                    'paths': count_paths,
                    'format_path': format_path
                }
            )
        }

format: format of the output. (default '\?color=paths [\?if=paths ●|■]')
format_path: format of the path output. (default '{basename}')
format_path_separator: show separator if more than one (default ' ')
path: the path(s) to a file or dir to check if it exists, take a list (default None)
Copy link
Contributor

@lasers lasers Jun 19, 2018

Choose a reason for hiding this comment

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

Too long imo. path: specify a string or a list of paths to check (default None)

}
```

@author obb, Moritz Lüdecke, Cyril Levis (@cyrinux), @lasers
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm. Thank you, but you can keep me out of this. I'm just helping you, bro. Thank you, bro. 👊

@cyrinux cyrinux force-pushed the file_status-allow-glob branch from a6a5992 to 24a5160 Compare June 19, 2018 12:14
@lasers
Copy link
Contributor

lasers commented Jun 19, 2018

So I toyed with this module... and made changes below. Changelog...

  • We did remove colors too. I updated the deprecation to reflect this.
  • Rename {fullpath} to {pathname} according to glob + basename descriptions.
  • Changed orders of color options, format, format_path. Color options goes last.
  • Stupid bug due to composite_join without formatting the path list.

If we set this...

    format = '{format_path}'
    format_path = '\?color=good {basename}'
    format_path_separator = '### '

..., the color will also be applied in the separator when it should not...

This requires format_separator = '\?color=white ,' instead. Reason: We join paths right away instead of formatting paths, putting it in a list, then joining. Users may not notice this or care, but I think this was an issue so with the diff, we don't colorize the separators too. You can test this by coloring format_path or format_separator before trying the diff.

  • Tweaks to skip format_path if it's not in format, make things in docs, kill some lines, but keep the coding standard, etc.
  • \?color=paths should not be used in format_path and format_separator because it'll be applied after the list... and is for format only... Also, with glob, we guarantee this to be always good so users should use \?color=good or any other color instead. (Just a minor thing to point out).
  • EDIT: an exception due to missing format_path = None. Fixed.
diff --git a/py3status/modules/file_status.py b/py3status/modules/file_status.py
index 4b306bef..2b074317 100644
--- a/py3status/modules/file_status.py
+++ b/py3status/modules/file_status.py
@@ -1,43 +1,48 @@
 # -*- coding: utf-8 -*-
 """
-Display if a files or directories exists.
+Display if files or directories exists.
 
 Configuration parameters:
-    cache_timeout: how often to run the check (default 10)
-    format: format of the output. (default '\?color=paths [\?if=paths ●|■]')
-    format_path: format of the path output. (default '{basename}')
+    cache_timeout: refresh interval for this module (default 10)
+    format: display format for this module
+        (default '\?color=paths [\?if=paths ●|■]')
+    format_path: format for paths (default '{basename}')
     format_path_separator: show separator if more than one (default ' ')
     path: specify a string or a list of paths to check (default None)
-    thresholds: specify color thresholds to use (default [(0, 'bad'), (1, 'good')])
-
-Color options:
-    color_bad: Error or file/directory does not exist
-    color_good: File or directory exists
+    thresholds: specify color thresholds to use
+        (default [(0, 'bad'), (1, 'good')])
 
 Format placeholders:
-    {format_path} paths of matching files
+    {format_path} format for paths
     {paths} number of paths, eg 1, 2, 3
 
-format_path path placeholders:
-    {basename} basename of matching files
-    {fullpath} fullpath of matching files
+format_path placeholders:
+    {basename} basename of pathname
+    {pathname} pathname
+
+Color options:
+    color_bad: files or directories does not exist
+    color_good: files or directories exists
+
+Color thresholds:
+    format:
+        paths: print a color based on the number of paths
 
 Examples:
-```
-# check files with wildcard, or contain user path, full paths
+# ``` (lol)
+# add multiple paths with wildcard or with pathnames
 file_status {
-    path = ['/tmp/test*', '~user/test1']
-    format = u'\?if=paths ● {format_path}|■ no files found'
-    format_path = '{fullpath}'
+    path = ['/tmp/test*', '~user/test1', '~/Videos/*.mp4']
 }
 
-# change color on files match
+# colorize basenames
 file_status {
-    path = ['/tmp/test*', '~user/test1']
-    format = u'\?color=paths ●'
-    thresholds = [(0, 'bad'), (1, 'good')]
+    path = '~/.config/i3/modules/*.py'
+    format = '{format_path}'
+    format_path = '\?color=good {basename}'
+    format_path_separator = ', '
 }
-```
+# ``` (lol)
 
 @author obb, Moritz Lüdecke, Cyril Levis (@cyrinux)
 
@@ -51,7 +56,7 @@ missing
 from glob import glob
 from os.path import basename, expanduser
 
-ERR_NO_PATH = 'no path given'
+STRING_NO_PATH = 'missing path'
 DEFAULT_FORMAT = u'\?color=paths [\?if=paths ●|■]'
 
 
@@ -61,8 +66,8 @@ class Py3status:
     # available configuration parameters
     cache_timeout = 10
     format = DEFAULT_FORMAT
-    format_path = u'{basename}'
-    format_path_separator = u' '
+    format_path = '{basename}'
+    format_path_separator = ' '
     path = None
     thresholds = [(0, 'bad'), (1, 'good')]
 
@@ -83,73 +88,71 @@ class Py3status:
         }
 
     def post_config_hook(self):
+        if not self.path:
+            raise Exception(STRING_NO_PATH)
+
         # deprecation
         on = getattr(self, 'icon_available', None)
         off = getattr(self, 'icon_unavailable', None)
         if self.format == DEFAULT_FORMAT and (on or off):
-            self.format = u'\?if=paths {}|{}'.format(on or u'●', off or u'■')
+            new_format = u'\?color=paths [\?if=paths {}|{}]'
+            self.format = new_format.format(on or u'●', off or u'■')
             msg = 'DEPRECATION: you are using old style configuration '
             msg += 'parameters you should update to use the new format.'
             self.py3.log(msg)
 
-        if self.path is None:
-            return {
-                'color': self.py3.COLOR_ERROR or self.py3.COLOR_BAD,
-                'full_text': ERR_NO_PATH,
-                'cached_until': self.py3.CACHE_FOREVER,
-            }
-
-        # backward compatibility, str to list
+        # convert str to list + expand path
         if not isinstance(self.path, list):
             self.path = [self.path]
-        # expand user paths
         self.path = list(map(expanduser, self.path))
 
-        self.init = {
-            'format_path': self.py3.get_placeholders_list(self.format_path)
-        }
+        # init
+        self.init = {'format_path': []}
+        if self.py3.format_contains(self.format, 'format_path'):
+            self.init['format_path'] = self.py3.get_placeholders_list(
+                self.format_path
+            )
 
     def file_status(self):
-        # init datas
         paths = sorted([files for path in self.path for files in glob(path)])
-        paths_number = len(paths)
+        count_path = len(paths)
+        format_path = None
 
-        # format paths
         if self.init['format_path']:
-            format_path = {}
+            new_data = []
             format_path_separator = self.py3.safe_format(
                 self.format_path_separator
             )
 
-            for key in self.init['format_path']:
-                if key == 'basename':
-                    temps_paths = map(basename, paths)
-                elif key == 'fullpath':
-                    temps_paths = paths
-                else:
-                    continue
-                format_path[key] = self.py3.composite_join(
-                    format_path_separator, temps_paths
-                )
-
-            format_path = self.py3.safe_format(self.format_path, format_path)
+            for pathname in paths:
+                path = {}
+                for key in self.init['format_path']:
+                    if key == 'basename':
+                        value = basename(pathname)
+                    elif key == 'pathname':
+                        value = pathname
+                    else:
+                        continue
+                    path[key] = self.py3.safe_format(value)
+                new_data.append(self.py3.safe_format(self.format_path, path))
+
+            format_path = self.py3.composite_join(
+                format_path_separator, new_data
+            )
 
-        # get thresholds
         if self.thresholds:
-            self.py3.threshold_get_color(paths_number, 'paths')
+            self.py3.threshold_get_color(count_path, 'paths')
 
-        response = {
+        return {
             'cached_until': self.py3.time_in(self.cache_timeout),
             'full_text': self.py3.safe_format(
                 self.format, {
-                    'paths': paths_number,
+                    'paths': count_path,
                     'format_path': format_path
                 }
             )
         }
 
-        return response
-
 
 if __name__ == "__main__":
     """

@cyrinux cyrinux force-pushed the file_status-allow-glob branch from be50c6d to 8fa66b0 Compare June 20, 2018 07:32
@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 20, 2018

Thanks @lasers , retyping slowy your diff, think I have understand what you have done. Cool learning python, property 💩 and 🇺🇸 with you. Thanks bro.

Copy link
Contributor

@lasers lasers left a comment

Choose a reason for hiding this comment

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

I would make a terrible teacher as I did some work for you. Beside, I'm learning too and it's more fun to do Python with family. ;-)

color_good: File or directory exists
cache_timeout: refresh interval for this module (default 10)
format: display format for this module
(default '\?color=paths [\?if=paths ●|■]')
Copy link
Contributor

Choose a reason for hiding this comment

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

If I remember it correctly, the family mentioned something about storing icons properly, eg (default '\?color=paths [\?if=paths \u25cf|\u25a0]') so I assume we should change it everywhere to be similar to SAMPLE OUTPUT.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What is the goal? For readability? Compliance?

Copy link
Contributor

@lasers lasers Jun 20, 2018

Choose a reason for hiding this comment

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

I don't remember all the details. I think readability so some things are not rendered as blocks or to avoid cause minor confusion. It may or may not had to do more with control characters. ~~EDIT: Maybe wait for the family.~~~

FILE_SEPARATOR = u' '
GROUP_SEPARATOR = u' '
RECORD_SEPARATOR = u' ' 
UNIT_SEPARATOR = u' '

versus more explicit...

FILE_SEPARATOR = u'\u231a'
GROUP_SEPARATOR = u'\u231d'
RECORD_SEPARATOR = u'\u231e' 
UNIT_SEPARATOR = u'\u231f'


@author obb, Moritz Lüdecke
format_path path placeholders:
Copy link
Contributor

Choose a reason for hiding this comment

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

format_path path placeholders:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nitpick :)


ERR_NO_PATH = 'no path given'
STRING_NO_PATH = 'no path given'
Copy link
Contributor

@lasers lasers Jun 20, 2018

Choose a reason for hiding this comment

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

missing path for more consistency with other modules.. and feels more family friendly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nitpick :)

off = getattr(self, 'icon_unavailable', None)
if self.format == DEFAULT_FORMAT and (on or off):
self.format = u'\?if=paths {}|{}'.format(on or u'●', off or u'■')
new_format = u'\?color=paths [\?if=paths {}|{}]'
Copy link
Contributor

Choose a reason for hiding this comment

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

We forget to replace {icon} with new_format. See if you can fix this.

Copy link
Contributor Author

@cyrinux cyrinux Jun 20, 2018

Choose a reason for hiding this comment

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

Not sure to understand, we don't need {icon} in new format no? And if I use legacy style I see my icon_available or icon_unavailable and I have deprecation log.

Copy link
Contributor

@lasers lasers Jun 20, 2018

Choose a reason for hiding this comment

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

That removes the icon_* okay... and for default format only, but not the old existing format. We need to keep the old format alive too... eg format = 'VPN {icon}' shouldn't break.

@cyrinux cyrinux force-pushed the file_status-allow-glob branch from 3f2c934 to fb4c723 Compare June 20, 2018 22:01
@lasers
Copy link
Contributor

lasers commented Jun 20, 2018

I think this is better done in the post_config_hook instead. Lines are also simplified when we don't compare + log. Not sure if that'll fly okay with the family, but this is almost done.

diff --git a/py3status/modules/file_status.py b/py3status/modules/file_status.py
index a5f1b005..9c01770d 100644
--- a/py3status/modules/file_status.py
+++ b/py3status/modules/file_status.py
@@ -57,7 +57,6 @@ from glob import glob
 from os.path import basename, expanduser
 
 STRING_NO_PATH = 'missing path'
-DEFAULT_FORMAT = u'\?color=paths [\?if=paths \u25cf|\u25a0]'
 
 
 class Py3status:
@@ -65,7 +64,7 @@ class Py3status:
     """
     # available configuration parameters
     cache_timeout = 10
-    format = DEFAULT_FORMAT
+    format = u'\?color=paths [\?if=paths \u25cf|\u25a0]'
     format_path = u'{basename}'
     format_path_separator = u' '
     path = None
@@ -91,16 +90,11 @@ class Py3status:
         if not self.path:
             raise Exception(STRING_NO_PATH)
 
-        # deprecation
-        self.on = getattr(self, 'icon_available', None)
-        self.off = getattr(self, 'icon_unavailable', None)
-        if self.format == DEFAULT_FORMAT and (self.on or self.off):
-            self.format = u'\?if=paths {}|{}'.format(self.on or u'\u25cf', self.off or u'\u25a0')
-            new_format = u'\?color=paths [\?if=paths {}|{}]'
-            self.format = new_format.format(self.on or u'\u25cf', self.off or u'\u25a0')
-            msg = 'DEPRECATION: you are using old style configuration '
-            msg += 'parameters you should update to use the new format.'
-            self.py3.log(msg)
+        # icon deprecation
+        on = getattr(self, 'icon_available', u'\u25cf')
+        off = getattr(self, 'icon_unavailable', u'\u25a0')
+        new_icon = u'\?color=paths [\?if=paths {}|{}]'.format(on, off)
+        self.format = self.format.replace('{icon}', new_icon)
 
         # convert str to list + expand path
         if not isinstance(self.path, list):
@@ -109,7 +103,9 @@ class Py3status:
 
         self.init = {'format_path': []}
         if self.py3.format_contains(self.format, 'format_path'):
-            self.init['format_path'] = self.py3.get_placeholders_list(self.format_path)
+            self.init['format_path'] = self.py3.get_placeholders_list(
+                self.format_path
+            )
 
     def file_status(self):
         # init datas
@@ -117,19 +113,12 @@ class Py3status:
         count_path = len(paths)
         format_path = None
 
-        # format icon
-        if self.py3.format_contains(self.format, 'icon'):
-            if count_path > 0:
-                icon = self.on
-            else:
-                icon = self.off
-
         # format paths
         if self.init['format_path']:
             new_data = []
             format_path_separator = self.py3.safe_format(
-                self.format_path_separator)
-
+                self.format_path_separator
+            )
             for pathname in paths:
                 path = {}
                 for key in self.init['format_path']:
@@ -156,7 +145,6 @@ class Py3status:
                 self.format, {
                     'paths': count_path,
                     'format_path': format_path,
-                    'icon': icon
                 }
             )
         }

@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 21, 2018

👍 I tried 🥇

@cyrinux cyrinux force-pushed the file_status-allow-glob branch from 4fb7243 to 67e26e6 Compare June 21, 2018 06:54
self.py3.log(msg)
# icon deprecation
on = getattr(self, 'icon_available', None)
off = getattr(self, 'icon_unavailable', None)
Copy link
Contributor

Choose a reason for hiding this comment

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

Not same from diff I gave you. {icon} display None instead of \u... here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oups. 😜

Copy link
Contributor

@lasers lasers left a comment

Choose a reason for hiding this comment

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

Nice work. I'd rename this to something else to be clear that this is more than allow several path.

Changelog:

  • Allow several paths.
  • So we add a number of {paths}.
  • And we add thresholds for {paths}.
  • And we add format_path config to print pathnames or basenames in the bar.

Deprecations:

  • Replace {icons} with if=paths... (killing icon configs)
  • Replace colors with threshold (killing hardcoded coloring)

Cheers. 🤕 👊 🥇

@cyrinux cyrinux changed the title file_status: allow several path file_status: allow several paths, new format Jun 22, 2018
@cyrinux
Copy link
Contributor Author

cyrinux commented Jun 22, 2018

Is title "file_status: allow several paths, new format" sufficiant?

Thanks for your patience @lasers 👊 🐤 🍻

@ultrabug
Copy link
Owner

ultrabug commented Jul 5, 2018

Tested OK, backward compatible, thanks 👍

@ultrabug ultrabug merged commit 4a11583 into ultrabug:master Jul 5, 2018
@lasers
Copy link
Contributor

lasers commented Jul 7, 2018

@cyrinux Sorry. I like things to be consistent. There was something slightly off about this module. Now I know why. When we made path accept multiple paths, we neglect to rename path to paths (plural) to stay in consistent with other plural configs... eg days = 4, sensors = [], filters = [], events = [] in other modules.

Doing this would also allow us to use non-plural placeholders (+ color names). It also would allow us to reserve paths for total paths similar to {messages}, but I think we will never do that here anyway.

So, can you please make this PR? 🤦‍♂️

diff --git a/py3status/modules/file_status.py b/py3status/modules/file_status.py
index 3bb29066..77fbbc81 100644
--- a/py3status/modules/file_status.py
+++ b/py3status/modules/file_status.py
@@ -5,16 +5,16 @@ Display if files or directories exists.
 Configuration parameters:
     cache_timeout: refresh interval for this module (default 10)
     format: display format for this module
-        (default '\?color=paths [\?if=paths ●|■]')
+        (default '\?color=path [\?if=path ●|■]')
     format_path: format for paths (default '{basename}')
     format_path_separator: show separator if more than one (default ' ')
-    path: specify a string or a list of paths to check (default None)
+    paths: specify a string or a list of paths to check (default None)
     thresholds: specify color thresholds to use
         (default [(0, 'bad'), (1, 'good')])
 
 Format placeholders:
     {format_path} format for paths
-    {paths} number of paths, eg 1, 2, 3
+    {path} number of paths, eg 1, 2, 3
 
 format_path placeholders:
     {basename} basename of pathname
@@ -26,23 +26,23 @@ Color options:
 
 Color thresholds:
     format:
-        paths: print a color based on the number of paths
+        path: print a color based on the number of paths
 
 Examples:
-```
+#``` (undo this line)
 # add multiple paths with wildcard or with pathnames
 file_status {
-    path = ['/tmp/test*', '~user/test1', '~/Videos/*.mp4']
+    paths = ['/tmp/test*', '~user/test1', '~/Videos/*.mp4']
 }
 
 # colorize basenames
 file_status {
-    path = ['~/.config/i3/modules/*.py']
+    paths = ['~/.config/i3/modules/*.py']
     format = '{format_path}'
     format_path = '\?color=good {basename}'
     format_path_separator = ', '
 }
-```
+#``` (undo this line)
 
 @author obb, Moritz Lüdecke, Cyril Levis (@cyrinux)
 
@@ -64,7 +64,7 @@ class Py3status:
     """
     # available configuration parameters
     cache_timeout = 10
-    format = u'\?color=paths [\?if=paths \u25cf|\u25a0]'
+    format = u'\?color=path [\?if=path \u25cf|\u25a0]'
     format_path = u'{basename}'
     format_path_separator = u' '
     path = None
@@ -83,23 +83,28 @@ class Py3status:
                     'new': 'icon_unavailable',
                     'msg': 'obsolete parameter use `icon_unavailable`'
                 },
+                {
+                    'param': 'path',
+                    'new': 'paths',
+                    'msg': 'obsolete parameter use `paths`'
+                },
             ],
         }
 
     def post_config_hook(self):
-        if not self.path:
+        if not self.paths:
             raise Exception(STRING_NO_PATH)
 
         # icon deprecation
         on = getattr(self, 'icon_available', u'\u25cf')
         off = getattr(self, 'icon_unavailable', u'\u25a0')
-        new_icon = u'\?color=paths [\?if=paths {}|{}]'.format(on, off)
+        new_icon = u'\?color=path [\?if=path {}|{}]'.format(on, off)
         self.format = self.format.replace('{icon}', new_icon)
 
         # convert str to list + expand path
-        if not isinstance(self.path, list):
-            self.path = [self.path]
-        self.path = list(map(expanduser, self.path))
+        if not isinstance(self.paths, list):
+            self.paths = [self.paths]
+        self.paths = list(map(expanduser, self.paths))
 
         self.init = {'format_path': []}
         if self.py3.format_contains(self.format, 'format_path'):
@@ -109,7 +114,7 @@ class Py3status:
 
     def file_status(self):
         # init datas
-        paths = sorted([files for path in self.path for files in glob(path)])
+        paths = sorted([files for path in self.paths for files in glob(path)])
         count_path = len(paths)
         format_path = None
 
@@ -137,14 +142,13 @@ class Py3status:
             )
 
         if self.thresholds:
-            self.py3.threshold_get_color(count_path, 'paths')
+            self.py3.threshold_get_color(count_path, 'path')
 
         return {
-            'cached_until':
-            self.py3.time_in(self.cache_timeout),
+            'cached_until': self.py3.time_in(self.cache_timeout),
             'full_text': self.py3.safe_format(
                 self.format, {
-                    'paths': count_path,
+                    'path': count_path,
                     'format_path': format_path
                 }
             )

@cyrinux
Copy link
Contributor Author

cyrinux commented Jul 7, 2018

Hi @lasers, ok I will done it

@cyrinux
Copy link
Contributor Author

cyrinux commented Jul 7, 2018

@lasers #1389

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.

3 participants