Commit 175d545bc9ab7eac80416423415a0b916fcad8cf

Authored by Alain Klotz
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=}")
... ...