bpo-32713: Fix tarfile.itn for large/negative float values. (GH-5434)
[python-delta-tar] / testing / create_pseudo_random_files.py
1 #!/usr/bin/env python3
2
3 import argparse
4 import os
5 import random
6 import string
7 from hashlib import sha512 as hashfunc
8
9
10 def create_rand_name(size=None):
11     """ Create rand name using alphanumeric char.
12         Param size: size of str name.
13         Type size: int.
14         Return: random name.
15         Rtype: str.
16     """
17     if not size:
18         size = random.randint(5, 15)
19     name = ''
20     for x in range(size):
21         name += random.choice(string.hexdigits)
22     return name
23
24
25 def create_rand_folder(directory):
26     """ Create rand folder in directory.
27         Param directory: folder where create new rand folder.
28         Type directory: str.
29         Return: path with new directory.
30         Rtype: str.
31     """
32     new_dir = os.path.join(directory, create_rand_name())
33     if not os.path.exists(new_dir):
34         os.makedirs(new_dir)
35     else:
36         new_dir = create_rand_folder(directory)
37     return new_dir
38
39
40 def create_rand_cad(size=1024):
41     """ Create rand str using hexadecimal char and hash sha512.
42         Param size: size in byte of str for generate.
43         Type size: int.
44         Return: random name.
45         Rtype: str.
46     """
47     cads = [hashfunc(create_rand_name().encode('utf-8')).hexdigest()]
48     last = cads[0]
49     for i in range(int(size / 128)):
50         last = hashfunc(last[:8].encode('utf-8')).hexdigest()
51         cads.append(last)
52     return ''.join(cads)[:size]
53
54
55 def create_file(path, size):
56     """ Get rand name using alphanumeric char.
57         Param size: size of str name.
58         Type size: int.
59         Return: random name.
60         Rtype: str.
61     """
62     filename = create_rand_name()
63     new_file = os.path.join(path, filename)
64     if not os.path.exists(new_file):
65         with open(new_file, 'w') as f:
66             f.write(create_rand_cad(size))
67         return new_file
68     else:
69         return create_file(path, size)
70
71
72 def generate_list_sizes(nfile, size, distribute_size):
73     """ Generate list of size for use it with create_files.
74         Param nfile: .
75         Type nfile: .
76         Param size: .
77         Type size: .
78         Param distribute_size: .
79         Type distribute_size: .
80         Return: .
81         Rtype: .
82     """
83     list_sizes = []
84     aux_size = size
85     normal_size = int(size / nfile)
86     var = max(1, int(normal_size - normal_size * distribute_size / 100))
87     for s in range(nfile):
88         if aux_size <= 0:
89             list_sizes.append(0)
90             continue
91         tmp_size = random.randint(normal_size - var, normal_size + var)
92         aux_size -= tmp_size
93         if tmp_size < 0:
94             list_sizes.append(tmp_size + aux_size)
95         else:
96             list_sizes.append(tmp_size)
97     return list_sizes
98
99
100 def get_files_per_folder(nfile, ndir, distribute_files):
101     """ Get numbers of files for each folder.
102         Param nfile: .
103         Type nfile: .
104         Param ndir: .
105         Type ndir: .
106         Param distribute_files: .
107         Type distribute_files: .
108         Return: List of numbers.
109         Rtype: list(int).
110     """
111     list_files = []
112     aux_files = nfile
113     f_per_dir = int(nfile / ndir)
114     f_remainder = int(nfile % ndir)
115     for d in range(ndir):
116         if (aux_files <= 0):
117             list_files.append(0)
118             continue
119         files = 0
120         if (f_per_dir > 0):
121             var = max(1, int(f_per_dir - f_per_dir * distribute_files / 100))
122             files += random.randint(f_per_dir - var, f_per_dir + var)
123         var = f_remainder - f_remainder * distribute_files // 100
124         files += random.randint(f_remainder - var, f_remainder + var)
125         aux_files -= files
126         if (aux_files <= 0):
127             list_files.append(files + aux_files)
128             continue
129         list_files.append(files)
130     if (aux_files > 0):
131         list_files[-1] += aux_files
132     return list_files
133
134
135 def main(args = None):
136     parser = argparse.ArgumentParser(description='Wgeneration option. ')
137     parser.add_argument('--seed', type=int, action='store', help='Seed. ')
138     parser.add_argument('--ndir', type=int, action='store',
139             help='Number of directories for create. ')
140     parser.add_argument('--deep', type=int, action='store',
141             help='Percent for distribute deep.')
142     parser.add_argument('--nfile', type=int, action='store',
143             help='Number of files for create. ')
144     parser.add_argument('--size', type=int, action='store',
145             help='Total size of files (MB) ')
146     parser.add_argument('--distribute_files', type=int, action='store',
147             help='Percent for distribute files. ')
148     parser.add_argument('--distribute_size', type=int, action='store',
149             help='Percent to distribute size of files. ')
150     parser.add_argument('--path', action='store', help='Path to generate. ')
151
152     if not args:
153         parsed_args = parser.parse_args()
154     else:
155         parsed_args = parser.parse_args(args)
156
157     if parsed_args.seed is not None:
158         seed = parsed_args.seed
159     else:
160         seed = random.randint(0, 1000000000)
161     random.seed(seed)
162     if parsed_args.ndir is not None:
163         ndir = parsed_args.ndir
164     else:
165         ndir = random.randint(0, 50000)
166     if parsed_args.deep is not None:
167         deep = parsed_args.deep
168     else:
169         deep = random.randint(0, 100)
170     if parsed_args.nfile:
171         nfile = parsed_args.nfile
172     else:
173         nfile = random.randint(1, 500000)
174     if parsed_args.size:
175         size = parsed_args.size * 1024 * 1024 # MB to byte
176     else:
177         size = random.randint(1, 5000)
178         size = size * 1024 * 1024 # MB to byte
179     if parsed_args.distribute_files is not None:
180         distribute_files = parsed_args.distribute_files
181     else:
182         distribute_files = random.randint(0, 100)
183     if parsed_args.distribute_size is not None:
184         distribute_size = parsed_args.distribute_size
185     else:
186         distribute_size = random.randint(0, 100)
187     if parsed_args.path:
188         path = os.path.abspath(parsed_args.path)
189         if not os.path.exists(path):
190             os.makedirs(path)
191     else:
192         path = os.getcwd()
193
194     print("Using seed %d: " % seed)
195     print("Generate %d folders with %d%% of deep." % (ndir, deep))
196     print("Generate %d files with total size %d MB." % (nfile,
197             size / 1024 / 1024))
198     print("\tDistribute (files, size): (%d%%, %d%%)." % (distribute_files,
199             distribute_size))
200
201     list_dir = [[path, ndir, nfile]]
202     list_sizes = generate_list_sizes(nfile, size, distribute_size)
203     list_files = get_files_per_folder(nfile, ndir, distribute_files)
204
205     while ndir > 0:
206         new_dir = create_rand_folder(list_dir[0][0])
207         ndir -= 1
208         for i in range(list_files[0]):
209             create_file(new_dir, list_sizes[i])
210         del list_sizes[:list_files[0]]
211         del list_files[0]
212         current_ndir = list_dir[0][1] - 1
213         if (current_ndir == 0):
214             del list_dir[0]
215         else:
216             ndir_deep = current_ndir * deep / 100
217             ndir_path = current_ndir - ndir_deep
218             if (ndir_deep > 0):
219                 list_dir.append([new_dir, ndir_deep])
220             if (ndir_path > 0):
221                 list_dir[0][1] = ndir_path
222             else:
223                 del list_dir[0]
224     return seed
225
226
227 if __name__ == "__main__":
228     main()