Commit 175d545bc9ab7eac80416423415a0b916fcad8cf
1 parent
a95d56f2
Exists in
master
Bug fix in FileNames.
Showing
1 changed file
with
212 additions
and
46 deletions
Show diff stats
src/guitastro/filenames.py
... | ... | @@ -1037,7 +1037,13 @@ class FileNames(FileNamesException, GuitastroTools): |
1037 | 1037 | return param |
1038 | 1038 | |
1039 | 1039 | def _naming_get_indexed1(self, fname): |
1040 | + """Return a dict of the semantic analysis for Indexed.1 | |
1041 | + | |
1042 | + Take account for wildcard characters. | |
1043 | + """ | |
1044 | + param = {} | |
1040 | 1045 | # --- search the separator for index |
1046 | + is_sep = False | |
1041 | 1047 | seps = ['.', '_', '-'] |
1042 | 1048 | kseps = [] |
1043 | 1049 | k = len(fname) - 1 |
... | ... | @@ -1051,10 +1057,13 @@ class FileNames(FileNamesException, GuitastroTools): |
1051 | 1057 | subb = fname[k1+1:] |
1052 | 1058 | index = "" |
1053 | 1059 | for sub in subb: |
1054 | - if sub.isdigit(): | |
1060 | + if sub.isdigit() or sub == "*" or sub == "?": | |
1055 | 1061 | index += sub |
1062 | + else: | |
1063 | + break | |
1056 | 1064 | if len(index) > 0: |
1057 | 1065 | index_indexes = [k1+1, k1+1+len(index)] |
1066 | + is_sep = True | |
1058 | 1067 | break |
1059 | 1068 | if index_indexes == []: |
1060 | 1069 | param['genename'] = fname |
... | ... | @@ -1067,9 +1076,9 @@ class FileNames(FileNamesException, GuitastroTools): |
1067 | 1076 | k2 = -1 |
1068 | 1077 | k = len(fname) |
1069 | 1078 | for car in fname[::-1]: |
1070 | - if car.isdigit(): | |
1079 | + if car.isdigit() or car == "*" or car == "?": | |
1071 | 1080 | if k2 == -1: |
1072 | - k2 = k | |
1081 | + k2 = k + 1 | |
1073 | 1082 | if k2 >=0 and not car.isdigit(): |
1074 | 1083 | k1 = k |
1075 | 1084 | break |
... | ... | @@ -1081,15 +1090,48 @@ class FileNames(FileNamesException, GuitastroTools): |
1081 | 1090 | if len(index_indexes) == 2: |
1082 | 1091 | k1, k2 = index_indexes |
1083 | 1092 | param['genename'] = fname[:k1-1] |
1084 | - param['sep'] = fname[k1-1] | |
1085 | - param['indexes'] = fname[k1:k2] | |
1086 | - if param['indexes'][0] == '0': | |
1093 | + if is_sep: | |
1094 | + param['sep'] = fname[k1-1] | |
1095 | + param['indexes'] = fname[k1:k2] | |
1096 | + else: | |
1097 | + param['indexes'] = fname[k1-1:k2] | |
1098 | + if param['indexes'][0] == '0' or param['indexes'][0] == '?': | |
1087 | 1099 | param['ndigit'] = len(param['indexes']) |
1088 | 1100 | else: |
1089 | 1101 | param['ndigit'] = 0 |
1090 | 1102 | param['suffix'] = fname[k2:] |
1103 | + else: | |
1104 | + if param['genename'][-1] == "*" and param['indexes'] == "": | |
1105 | + param['genename'] = param['genename'][:-1] | |
1106 | + param['indexes'] = "*" | |
1107 | + if param['genename'] == "" and param['indexes'] == "*": | |
1108 | + param['genename'] = "*" | |
1109 | + param['indexes'] = "" | |
1091 | 1110 | return param |
1092 | 1111 | |
1112 | + def naming_wildcard(self) -> str: | |
1113 | + """Return the wildcard corresponding to the naming rule | |
1114 | + | |
1115 | + Returns: | |
1116 | + The wildcard corresponding to the naming rule. | |
1117 | + | |
1118 | + """ | |
1119 | + if self.fcontext_value('naming') == self.NAMING_NONE: | |
1120 | + wildcard = "*" | |
1121 | + elif self.fcontext_value('naming') == self.NAMING_PYROS_IMG1: | |
1122 | + wildcard = "???_????????_????????????_?_???_???_??????????_???_???" | |
1123 | + elif self.fcontext_value('naming') == self.NAMING_PYROS_EPH1: | |
1124 | + wildcard = "????_????????_?_???_*" | |
1125 | + elif self.fcontext_value('naming') == self.NAMING_PYROS_SEQ1: | |
1126 | + wildcard = "????_????????_?_???_??????????" | |
1127 | + elif self.fcontext_value('naming') == self.NAMING_ROS1: | |
1128 | + wildcard = "??_????????_?????????_??????_????????" | |
1129 | + elif self.fcontext_value('naming') == self.NAMING_T1M1: | |
1130 | + wildcard = "T1M_????????_??????_???_*_Filtre_*_bin?x?.*" | |
1131 | + elif self.fcontext_value('naming') == self.NAMING_INDEXED1: | |
1132 | + wildcard = "*" | |
1133 | + return wildcard | |
1134 | + | |
1093 | 1135 | def naming_set(self, *args, **kwargs) -> str: |
1094 | 1136 | """Set a file name formed by input parameters according the current naming |
1095 | 1137 | |
... | ... | @@ -1125,20 +1167,7 @@ class FileNames(FileNamesException, GuitastroTools): |
1125 | 1167 | """ |
1126 | 1168 | see_rules = self._see_naming_rules |
1127 | 1169 | # --- wilcards |
1128 | - if self.fcontext_value('naming') == self.NAMING_NONE: | |
1129 | - wildcard = "*" | |
1130 | - elif self.fcontext_value('naming') == self.NAMING_PYROS_IMG1: | |
1131 | - wildcard = "???_????????_????????????_?_???_???_??????????_???_???" | |
1132 | - elif self.fcontext_value('naming') == self.NAMING_PYROS_EPH1: | |
1133 | - wildcard = "????_????????_?_???_*" | |
1134 | - elif self.fcontext_value('naming') == self.NAMING_PYROS_SEQ1: | |
1135 | - wildcard = "????_????????_?_???_??????????" | |
1136 | - elif self.fcontext_value('naming') == self.NAMING_ROS1: | |
1137 | - wildcard = "??_????????_?????????_??????_????????" | |
1138 | - elif self.fcontext_value('naming') == self.NAMING_T1M1: | |
1139 | - wildcard = "T1M_????????_??????_???_*_Filtre_*_bin?x?.*" | |
1140 | - elif self.fcontext_value('naming') == self.NAMING_INDEXED1: | |
1141 | - wildcard = "*" | |
1170 | + wildcard = self.naming_wildcard() | |
1142 | 1171 | # --- |
1143 | 1172 | na = len(args) |
1144 | 1173 | nk = len(kwargs) |
... | ... | @@ -1715,7 +1744,6 @@ class FileNames(FileNamesException, GuitastroTools): |
1715 | 1744 | for key, val in kwargs.items(): |
1716 | 1745 | if key in param.keys(): |
1717 | 1746 | param[key] = val |
1718 | - print(f"STEP 50 {param=}") | |
1719 | 1747 | # --- verify genename |
1720 | 1748 | valid = False |
1721 | 1749 | if isinstance(param['genename'],str): |
... | ... | @@ -2684,12 +2712,21 @@ class FileNames(FileNamesException, GuitastroTools): |
2684 | 2712 | |
2685 | 2713 | """ |
2686 | 2714 | p = pathlib.Path(fullfilename) |
2687 | - p = p.resolve() # eliminate .. | |
2715 | + try: | |
2716 | + p = p.resolve() # eliminate '..' if exist | |
2717 | + except: | |
2718 | + # p.resolve does not work with '*' characters | |
2719 | + pass | |
2688 | 2720 | absolute = p.absolute() |
2689 | 2721 | drive = absolute.drive |
2690 | 2722 | cwd = p.cwd() |
2691 | - dirname = p.parent | |
2723 | + dirname = str(p.parent) | |
2724 | + if '*' in dirname or '?' in dirname: | |
2725 | + wildcard_dirname = True | |
2726 | + else: | |
2727 | + wildcard_dirname = False | |
2692 | 2728 | basename = p.name # with suffixes |
2729 | + naming = self.naming_ident(basename) | |
2693 | 2730 | suffixes = p.suffixes |
2694 | 2731 | extension = "" # all the suffixes |
2695 | 2732 | for suffixe in suffixes: |
... | ... | @@ -2699,21 +2736,29 @@ class FileNames(FileNamesException, GuitastroTools): |
2699 | 2736 | name = basename[:k] # supress extension |
2700 | 2737 | else: |
2701 | 2738 | name = basename # has no extension |
2739 | + if '*' in name or '?' in name: | |
2740 | + wildcard_fname = True | |
2741 | + else: | |
2742 | + wildcard_fname = False | |
2702 | 2743 | parts = p.parts |
2703 | - naming = self.naming_ident(basename) | |
2704 | 2744 | dico = {} |
2705 | - dico['dirname'] = str(dirname) | |
2706 | - dico['fname'] = name | |
2745 | + # --- Initial input | |
2746 | + dico['input'] = str(p) | |
2747 | + dico['absolute'] = str(absolute) | |
2748 | + # --- Directory | |
2749 | + dico['dirname'] = dirname | |
2750 | + dico['wildcard_dirname'] = wildcard_dirname | |
2751 | + dico['parts'] = parts # dirname as a list | |
2752 | + dico['cwd'] = str(cwd) # current working dir (not necessarily dirname) | |
2753 | + dico['drive'] = drive | |
2754 | + # --- File name | |
2755 | + dico['fname'] = name # file name with no dirname and no extension | |
2756 | + dico['wildcard_fname'] = wildcard_fname # bool if fname is a wildcard | |
2757 | + dico['naming'] = naming | |
2758 | + # --- Extension | |
2707 | 2759 | dico['extension'] = extension |
2708 | - # -- | |
2709 | 2760 | dico['suffixes'] = suffixes # list |
2710 | - dico['parts'] = parts # list | |
2711 | - dico['naming'] = naming | |
2712 | 2761 | # -- |
2713 | - dico['input'] = str(p) | |
2714 | - dico['cwd'] = str(cwd) | |
2715 | - dico['drive'] = drive | |
2716 | - dico['absolute'] = str(absolute) | |
2717 | 2762 | return dico |
2718 | 2763 | |
2719 | 2764 | def join(self, filename:str = "") -> str: |
... | ... | @@ -2756,9 +2801,18 @@ class FileNames(FileNamesException, GuitastroTools): |
2756 | 2801 | out_fullname = fn.join(in_fullname) |
2757 | 2802 | |
2758 | 2803 | """ |
2759 | - if filename != "": | |
2804 | + if isinstance(filename, list): | |
2805 | + fname_ins = filename | |
2806 | + fname_outs = [] | |
2807 | + for filename in fname_ins: | |
2808 | + self.update_subdir_fname_from_filename(filename) | |
2809 | + fname_out = os.path.join(self.rootdir, self.subdir, self.fname + self.extension) | |
2810 | + fname_outs.append(fname_out) | |
2811 | + return fname_outs | |
2812 | + elif filename != "": | |
2760 | 2813 | self.update_subdir_fname_from_filename(filename) |
2761 | - return os.path.join(self.rootdir, self.subdir, self.fname + self.extension) | |
2814 | + fname_out = os.path.join(self.rootdir, self.subdir, self.fname + self.extension) | |
2815 | + return fname_out | |
2762 | 2816 | |
2763 | 2817 | def joinabs(self, filename:str = ""): |
2764 | 2818 | """Join the four parts of a context to get a full file name with absolute path. |
... | ... | @@ -2771,16 +2825,51 @@ class FileNames(FileNamesException, GuitastroTools): |
2771 | 2825 | |
2772 | 2826 | The full file name in a string with absolute path (rootdir, subdir, fname, extension) |
2773 | 2827 | """ |
2828 | + if isinstance(filename, list): | |
2829 | + fname_ins = filename | |
2830 | + fname_outs = [] | |
2831 | + for filename in fname_ins: | |
2832 | + fname_out = os.path.abspath(self.join(filename)) | |
2833 | + fname_outs.append(fname_out) | |
2834 | + return fname_outs | |
2774 | 2835 | return os.path.abspath(self.join(filename)) |
2775 | 2836 | |
2776 | - def glob(self, wildcard:str, *args) -> list: | |
2837 | + | |
2838 | + def glob(self, *args, **kwargs) -> list: | |
2777 | 2839 | """Glob from a wildcard. Add -R to be recursive. |
2840 | + | |
2841 | + Args: | |
2842 | + | |
2843 | + *args: | |
2844 | + | |
2845 | + * '-R': Recursive option | |
2846 | + * '-fc': Use the current fcontext option | |
2847 | + * (str): A wildcard with a complete path. The name must compatible with the current fcontext if the option "-fc" is present. | |
2848 | + | |
2849 | + *kwargs: Options when calling _join() in case of use of fcontext. | |
2850 | + | |
2851 | + Returns: | |
2852 | + | |
2853 | + A filename list of existing files of the disk verifying the wildcard. | |
2854 | + | |
2855 | + Examples: | |
2856 | + | |
2857 | + fn.glob("/tmp/user/M65*.fit", "-R") | |
2858 | + | |
2778 | 2859 | """ |
2779 | - p = pathlib.Path() | |
2780 | 2860 | recursif = False |
2861 | + use_fcontext = False | |
2781 | 2862 | for arg in args: |
2782 | - if arg=="-R": | |
2783 | - recursif = True | |
2863 | + if isinstance(arg, str): | |
2864 | + if arg == "-R": | |
2865 | + recursif = True | |
2866 | + if arg == "-fc": | |
2867 | + use_fcontext = True | |
2868 | + else: | |
2869 | + wildcard = arg | |
2870 | + if use_fcontext: | |
2871 | + wildcard = self._join(args, kwargs) | |
2872 | + p = pathlib.Path() | |
2784 | 2873 | if recursif: |
2785 | 2874 | res = p.rglob(wildcard) |
2786 | 2875 | else: |
... | ... | @@ -2788,6 +2877,71 @@ class FileNames(FileNamesException, GuitastroTools): |
2788 | 2877 | res = [str(re) for re in res] |
2789 | 2878 | return res |
2790 | 2879 | |
2880 | + def _join(self, *args, **kwargs) -> str: | |
2881 | + """ Build the complete any file name (folder and extension) or wildcard compatible with the current fcontext | |
2882 | + | |
2883 | + Args: | |
2884 | + | |
2885 | + *args: | |
2886 | + | |
2887 | + * '-f': Force to update the fcontext attributes | |
2888 | + * (str): A file name or wildcard compatible with the current fcontext | |
2889 | + | |
2890 | + **kwargs: | |
2891 | + | |
2892 | + * Any key of the fcontext to force at a given value | |
2893 | + | |
2894 | + Returns: | |
2895 | + | |
2896 | + A filename or a wildcard with the path and extension according the fcontext. | |
2897 | + | |
2898 | + Examples: | |
2899 | + | |
2900 | + fn._join("M65", "-f", sep="-", indexes="*") | |
2901 | + """ | |
2902 | + # --- Get parameters from *args | |
2903 | + fname_input = None | |
2904 | + pdict_input = {} | |
2905 | + force = False | |
2906 | + for arg in args: | |
2907 | + if isinstance(arg, str): | |
2908 | + if arg == "-f" or arg == "-force": | |
2909 | + force = True | |
2910 | + else: | |
2911 | + fname_input = arg | |
2912 | + pdict_input = self.dict(fname_input) | |
2913 | + # --- Default wilcard of the current fcontext | |
2914 | + param_wildcard = fn.naming_get(fn.naming_wildcard()) | |
2915 | + print(f"(100) {param_wildcard=}") | |
2916 | + # --- Get parameters from *kwargs compatible with the fcontext param keys | |
2917 | + param_inputs = {} | |
2918 | + for key, val in kwargs.items(): | |
2919 | + if key in param_wildcard: | |
2920 | + param_inputs[key] = val | |
2921 | + # --- Extract param from the fname_input | |
2922 | + if fname_input == None: | |
2923 | + # no file was provided | |
2924 | + param = param_wildcard | |
2925 | + else: | |
2926 | + # no file was provided | |
2927 | + param = self.naming_get(fname_input) | |
2928 | + print(f"(200) {param=}") | |
2929 | + # --- Set kwargs in the wilcard of the current fcontext | |
2930 | + for key, val in param_inputs.items(): | |
2931 | + param[key] = param_inputs[key] | |
2932 | + # --- Modify fcontext attributes if forced | |
2933 | + if force: | |
2934 | + print(f"{pdict_input=}") | |
2935 | + if pdict_input['wildcard_dirname'] == False and pdict_input['dirname'] != ".": | |
2936 | + self.rootdir = pdict_input['dirname'] | |
2937 | + self.extension = pdict_input['extension'] | |
2938 | + # --- Build the filename | |
2939 | + fname_input = self.naming_set(param) | |
2940 | + print(f"(300) {fname_input=}") | |
2941 | + fullname_input = self.joinabs(fname_input) | |
2942 | + print(f"{fullname_input=}") | |
2943 | + return fullname_input | |
2944 | + | |
2791 | 2945 | def split_dir_name_extension(self, fullfilename:str) -> Tuple[str, str, str]: |
2792 | 2946 | """Split a full filename into three parts: Path, name, extension |
2793 | 2947 | |
... | ... | @@ -3449,8 +3603,8 @@ class FileNames(FileNamesException, GuitastroTools): |
3449 | 3603 | |
3450 | 3604 | if __name__ == "__main__": |
3451 | 3605 | |
3452 | - default = 19 | |
3453 | - example = input(f"Select the example (0 to 19) ({default}) ") | |
3606 | + default = 20 | |
3607 | + example = input(f"Select the example (0 to 20) ({default}) ") | |
3454 | 3608 | try: |
3455 | 3609 | example = int(example) |
3456 | 3610 | except: |
... | ... | @@ -3851,23 +4005,35 @@ if __name__ == "__main__": |
3851 | 4005 | |
3852 | 4006 | if example == 19: |
3853 | 4007 | """ |
3854 | - Test PyROS indexed | |
4008 | + Test fcontext Indexed.1 | |
3855 | 4009 | """ |
3856 | - # --- Create a file context for ephemeris files | |
4010 | + # --- Create a file context | |
3857 | 4011 | fn.fcontext_create("findex", "Files with indexes") |
3858 | 4012 | fn.fcontext = "findex" |
3859 | 4013 | fn.pathnaming("Indexed.1") |
3860 | 4014 | fn.rootdir = "/tmp/eph" |
3861 | 4015 | fn.extension = ".f" |
3862 | 4016 | param = {} |
3863 | - param['genename'] = "M63-067" | |
4017 | + param['genename'] = "M63-078" | |
3864 | 4018 | param['sep'] = "-" |
3865 | - param['indexes'] = ['001', '002'] | |
4019 | + #param['indexes'] = ['001', '002'] | |
4020 | + param['indexes'] = '*' | |
3866 | 4021 | param['suffix'] = "R" |
3867 | 4022 | fname = fn.naming_set(param) |
3868 | 4023 | print(f"FINAL {fname=}") |
3869 | 4024 | param = fn.naming_get(fname) |
3870 | 4025 | print(f"FINAL {param=}") |
3871 | 4026 | out_fullname = fn.join(fname) |
3872 | - print(f"\n==== Create a file in the good path (context {fn.fdescription}) ====") | |
4027 | + print(f"==== Create a file in the good path (context = {fn.fdescription}) ====") | |
3873 | 4028 | print(f"{out_fullname=:}") |
4029 | + | |
4030 | + if example == 20: | |
4031 | + """ | |
4032 | + Test the method _naming_get_indexed1() of fcontext Indexed.1 | |
4033 | + """ | |
4034 | + # --- Create a file context | |
4035 | + fn.fcontext_create("findex", "Files with indexes") | |
4036 | + fn.fcontext = "findex" | |
4037 | + fn.pathnaming("Indexed.1") | |
4038 | + param = fn._naming_get_indexed1("M67-????R") | |
4039 | + print(f"{param=}") | ... | ... |