mathause / filefinder

find and parse file and folder names
MIT License
3 stars 1 forks source link

define reserved keywords? #97

Open mathause opened 1 day ago

mathause commented 1 day ago

Currently we don't have any sanity checks on the file pattern and path pattern. But I think there are some names that should be reserved - e.g. when they are used as keywords for methods, e.g. keys, on_parse_error, _allow_empty, we could either warn or raise if these are detected. We could also generally disallow anything with a leading underscore (but then I am not the biggest fan of keywords with underscores).

https://github.com/mathause/filefinder/blob/dc449bd57d0d2ad084ac42f37830a0dabeedd65d/filefinder/_filefinder.py#L336-L338

Example 1

import filefinder

ff = filefinder.FileFinder(
    path_pattern="",
    file_pattern="a_{keys}",
    test_paths=["a_1", "a_2", "a_3"]
)

ff.find_files()
```python-traceback --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[25], line 9 1 import filefinder 3 ff = filefinder.FileFinder( 4 path_pattern="", 5 file_pattern="a_{keys}", 6 test_paths=["a_1", "a_2", "a_3"] 7 ) ----> 9 ff.find_files() File ~/.conda/envs/mesmer_dev/lib/python3.12/site-packages/filefinder/_filefinder.py:432, in FileFinder.find_files(self, keys, on_parse_error, _allow_empty, **keys_kwargs) 386 def find_files( 387 self, keys=None, on_parse_error="raise", _allow_empty=False, **keys_kwargs 388 ): 389 """find files in the file system using the file pattern 390 391 Parameters (...) 430 431 """ --> 432 return self.full.find( 433 keys, 434 on_parse_error=on_parse_error, 435 _allow_empty=_allow_empty, 436 **keys_kwargs, 437 ) File ~/.conda/envs/mesmer_dev/lib/python3.12/site-packages/filefinder/_filefinder.py:107, in _Finder.find(self, keys, on_parse_error, _allow_empty, **keys_kwargs) 104 for one_search_dict in product_dict(**keys): 106 cond_dict = self._create_condition_dict(**one_search_dict) --> 107 full_pattern = self.create_name(**cond_dict) 109 paths = sorted(self._glob(full_pattern), key=natural_keys) 111 all_paths += paths File ~/.conda/envs/mesmer_dev/lib/python3.12/site-packages/filefinder/_filefinder.py:50, in _FinderBase.create_name(self, keys, **keys_kwargs) 38 def create_name(self, keys=None, **keys_kwargs): 39 """build name from keys 40 41 Parameters (...) 47 ``keys`` and ``keys_kwargs`` the latter takes priority. 48 """ ---> 50 keys = update_dict_with_kwargs(keys, **keys_kwargs) 52 return self._pattern_no_fmt_spec.format(**keys) File ~/.conda/envs/mesmer_dev/lib/python3.12/site-packages/filefinder/utils.py:91, in update_dict_with_kwargs(dictionary, **kwargs) 73 """update a dictionary with keyword arguments. The kwargs take precedence 74 75 Parameters (...) 87 {'a': 1, 'b': 3, 'c': 5} 88 """ 90 if not isinstance(dictionary, (dict, type(None))): ---> 91 raise TypeError( 92 f"First argument must be a dict or None, got '{type(dictionary).__name__}'" 93 ) 95 return (dictionary or {}) | kwargs TypeError: First argument must be a dict or None, got 'str' ```

Example 2

import filefinder

ff = filefinder.FileFinder(
    path_pattern="",
    file_pattern="a_{on_parse_error}",
    test_paths=["a_1", "a_2", "a_3"]
)

ff.find_files(on_parse_error="1")
mathause commented 21 hours ago

we could use a positional-only argument for keys

def test(keys, /, **kwargs):
    print(keys, kwargs)

test({"a": 5}, keys=7) # works
# {'a': 5} {'keys': 7}

def test(keys, **kwargs):
    print(keys, kwargs)

test({"a": 5}, keys=7) # fails
# TypeError: test() got multiple values for argument 'keys'

I don't think on_parse_error and _allow_empty are ever going to be used, but still good to have them error. We could also rename _allow_empty to allow_empty (but that't a separate issue & PR).