Completed
Push — master ( 043c13...edc126 )
by Sepand
01:03
created

print_logo()   A

Complexity

Conditions 4

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
dl 0
loc 7
rs 9.2
c 0
b 0
f 0
1
import shutil  # Library For Work With File In High Level Like Copy
2
import webbrowser
3
from params import *
4
import socket
5
import requests
6
import re
7
import time
8
import sys
9
import urllib.request
10
import platform
11
import random
12
13
meta_input = ""
14
15
def print_logo():
16
    if "logo.txt" in os.listdir():
17
        with open("logo.txt","r") as logo_file:
18
            for line in logo_file:
19
                print(line.rstrip())
20
    else:
21
        pass
22
def convert_bytes(num):
23
    """ convert num to idiomatic byte unit
24
25
    :param num: the input number.
26
    """
27
    for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
28
        if num < 1024.0:
29
            return "%3.1f %s" % (num, x)
30
        num /= 1024.0
31
32
33
def file_size():
34
    """ Print the size of output file
35
36
    """
37
    list_of_files = os.listdir(out_dir)
38
    response = 0
39
    for file in list_of_files:
40
        file_info = os.stat(os.path.join(out_dir, file))
41
        response += file_info.st_size
42
    print_line(70, "*")
43
    print("Used Space --> " + convert_bytes(response))
44
    print_line(70, "*")
45
46
47
def download_badge(address):
48
    """ Download badge for website
49
50
    :param address: the address that should get badge
51
    """
52
    r = requests.get(address, stream=True)
53
    with open(os.path.join(image_dir, "badge.svg"), 'wb') as f:
54
        shutil.copyfileobj(r.raw, f)
55
56
57
def random_badge_color():
58
    """return a random color for badge
59
60
    """
61
    random_index = random.randint(0, len(badge_color_list) - 1)
62
    return badge_color_list[random_index]
63
64
65
def system_details():
66
    """ Show detail of system that code is runnig on
67
68
    """
69
    return platform.node() + " , " + platform.processor() + " ,  " + platform.platform()
70
71
72
def generation_time(time_1=None):
73
    """ Calculate the generation time
74
75
    :param time_1: time that passed but not counted in generation time
76
    :return :the amount of time that passed .
77
    """
78
    if time_1 is None:
79
        return time.perf_counter()
80
    else:
81
        return time.perf_counter() - time_1
82
83
84
def find_global_ip():
85
    """ Find the ip for use in API
86
87
    :return: return the IP.
88
    """
89
    try:
90
        response = requests.get(ip_finder_api)
91
        return response.text[:-1]
92
    except:
93
        return "0.0.0.0"
94
95
96
def create_badge(subject="qpage", status=version, color="blue", random=False):
97
    if random:
98
        color = random_badge_color()
99
    else:
100
        if color not in badge_color_list:
101
            color = "orange"
102
    badge_adr = adv_badge_static + subject + "-" + status + "-" + color + '.svg'
103
    if internet():
104
        download_badge(badge_adr)
105
        return os.path.join(image_dir, "badge.svg")
106
    else:
107
        return badge_adr
108
109
110
def is_sample_downloaded():
111
    """ Check the sample site material is downloaded
112
113
    :return : list of the materials
114
    """
115
    download_list = []
116
    if "profile.png" not in os.listdir(image_dir):
117
        download_list.append(0)
118
    if "font.TTF" not in os.listdir(font_dir):
119
        download_list.append(1)
120
    if "resume.pdf" not in os.listdir(doc_dir) and "resume.txt" not in os.listdir(doc_dir):
121
        download_list.extend([2, 3])
122
    if "icon.ico" not in os.listdir(image_dir):
123
        download_list.append(4)
124
    return download_list
125
126
127
def download_lorem():
128
    """ Download the lorem file
129
130
    """
131
    if internet():
132
        urllib.request.urlretrieve("http://www.qpage.ir/sample/Latin-Lipsum.txt", "Latin-Lipsum.txt")
133
    else:
134
        print("Error In Download Lorem")
135
136
137
def read_lorem(char=100):
138
    """ find and read lorem
139
140
    :param char: the amount of char that needed
141
    :return : the lorme string
142
    """
143
    try:
144
        if "Latin-Lipsum.txt" not in os.listdir(work_dir):
145
            download_lorem()
146
        lorem_file = open("Latin-Lipsum.txt", "r")
147
        lorem_text = lorem_file.read()
148
        lorem_file.close()
149
        return " ".join(lorem_text.split(" ")[:char])
150
    except:
151
        return None
152
153
154
def sample_site_download(item_list):
155
    """Download sample material for make a fake site
156
157
    :param item_list: Download items form item_list
158
    """
159
    try:
160
        if internet():
161
            for i in item_list:
162
                print("Downloading " + sample_dict_message[i] + " . . . [" + str(i + 1) + "/5]")
163
                print_line(70)
164
                urllib.request.urlretrieve(list(sample_dict_addr.values())[i],
165
                                           os.path.join(image_dir, list(sample_dict_addr.keys())[i]))
166
            print("Done! All Material Downloaded")
167
            print_line(70)
168
        else:
169
            print("Error In Internet Connection!")
170
            print_line(70)
171
    except:
172
        print("Error in downloading sample files check your internet conection")
173
        print_line(70)
174
175
176
def logger(status=False, perf_time=None):
177
    """Show the log of the app
178
179
    :param status: show status of app.
180
    :param perf_time : show the time passed for generate files
181
    """
182
    file = open("build_log.txt", "a")
183
    if not status:
184
        file.write("Failed  " + str(datetime.datetime.now()) + "\n")
185
    else:
186
        file.write("Success " + str(datetime.datetime.now()) + "\n")
187
        file.write("Generation Time: " + str(perf_time) + "\n")
188
    file.close()
189
190
191
def print_line(number, char="-"):
192
    """ Print a Line
193
194
    :param number: the amount char that in lien
195
    :param char  : the char that used to draw line
196
    """
197
    line = ""
198
    i=0
199
    while(i<number):
200
        line+=char
201
        i+=1
202
    print(line)
203
204
205
def name_standard(name):
206
    """ return the Standard version of the input word
207
208
    :param name: the name that should be standard
209
    :return name: the standard form of word
210
    """
211
    reponse_name = name[0].upper() + name[1:].lower()
212
    return reponse_name
213
214
215
def address_print():
216
    """Print the working directory
217
218
    """
219
    print_line(70, "*")
220
    print("Where --> " + work_dir)
221
    print_line(70, "*")
222
223
224
def create_folder():
225
    """This Function Create Empty Folder At Begin
226
227
    """
228
    folder_flag = 0
229
    list_of_folders = os.listdir(work_dir)
230
    for i in ["doc", "image", "output", "font"]:
231
        if i not in list_of_folders:
232
            os.mkdir(i)
233
            folder_flag += 1
234
            if i == "doc":
235
                file = open(os.path.join(doc_dir, "index.txt"), "w")
236
                if read_lorem() is None:
237
                    file.write("This is For First Page . . .")
238
                else:
239
                    file.write(read_lorem())
240
                file.close()
241
    return bool(folder_flag)
242
243
244
def page_name_update():
245
    """This Function Update Page Names
246
247
    """
248
    for i in os.listdir(doc_dir):
249
        if i.find(".txt") != -1 and i[:-4].upper() != "INDEX":
250
            actual_name.append(i[:-4])
251
            page_name.append(i[:-4])
252
253
254
def menu_maker():
255
    """Top Menu Maker In each html page
256
257
    """
258
    result = "<center>"
259
    for i,item in enumerate(page_name):
260
        if item == "Home":
261
            targets_blank = ""
262
        else:
263
            targets_blank = 'target="blank"'
264
            # Hyper Link To Each Page In HTML File
265
        result += '\t<a href="' \
266
                    + actual_name[i] + '.html"' + targets_blank + '>' + name_standard(item) + "</a>\n"
267
        result += "&nbsp\n"
268
    result += "</center>"
269
    result = result + "\t\t" + break_line  # Add Break line to End Of The Menu
270
    return result  # Return All Of The Menu
271
272
273
def menu_writer():  #
274
    """Write menu_maker output in html and close file after
275
276
    """
277
    message = menu_maker()
278
    page_name_length=len(page_name)
279
    for i in range(page_name_length):
280
        file = open(os.path.join(out_dir, actual_name[i] + ".html"), "a")
281
        file.write(message)
282
        file.close()
283
284
285
def print_meta():
286
    """Add meta to html files
287
288
    :return static_meta: The meta that created
289
    """
290
    global meta_input
291
    meta_input = input("Please Enter Your Name : ")
292
    static_meta = '<meta name="description" content="Welcome to homepage of ' + meta_input + '"/>\n'
293
    static_meta += '<meta property="og:title" content="' + meta_input + '"/>\n'
294
    static_meta += '<meta property="og:site_name" content="' + meta_input + '"/>\n'
295
    static_meta += '<meta property="og:image" content="favicon.ico" />\n'
296
    if len(meta_input) < 4:
297
        warnings.append("[Warning] Your input for name is too short!!")
298
    return static_meta
299
300
301
def html_init(name):
302
    """Create Initial Form Of each Html Page Like Title And HTML  And Body Tag.
303
304
    :param name: the name of html file.
305
    """
306
307
    html_name = os.path.join(out_dir, name + ".html")
308
    file = open(html_name, "w")
309
    file.write("<html>\n")
310
    file.write("\t<head>\n")
311
    if name == "index":
312
        file.write("\t\t<title>Welcome To My Homepage</title>\n")
313
    else:
314
        file.write("\t\t<title>" + name_standard(name) + "</title>\n")
315
    file.write('<link rel="stylesheet" href="styles.css" type="text/css"/>\n')
316
    css_link = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'
317
    file.write('<link rel="stylesheet" href= ' + css_link + ' type="text/style"/>\n')
318
319
    if name == 'index':  # Add meta only for index page
320
        file.write(print_meta())
321
322
    file.write("\t</head>\n")
323
    file.write('\t<body class="body_tag">\n')
324
    file.close()
325
326
327
def html_end(name):
328
    """Create End Of The Html and close file
329
330
    :param name: The name of html file.
331
    """
332
    html_name = os.path.join(out_dir, name + ".html")
333
    file = open(html_name, "a")
334
    file.write("\t</body>\n")
335
    file.write("</html>")
336
    file.close()
337
338
339
def close_files():
340
    """Close all the files.
341
342
    """
343
    for i in files:
344
        if i.closed==False:
345
            i.close()
346
347
348
def LSM_translate(line, center):
349
    # TODO : write a document for this function
350
    """ ????
351
352
    :param line: the input line.
353
    :param center: put it in center
354
355
    :return : return a list contain text header end and header begin
356
    """
357
    line.strip()
358
    text = line
359
    header_start = '<h4 class="color_tag">'
360
    header_end = "</h4>"
361
    if line.find("[L]") != -1:
362
        header_start = '<h2 class="color_tag">'
363
        header_end = "</h2>"
364
        text = line[3:]
365
    elif line.find("[S]") != -1:
366
        header_start = '<h5 class="color_tag">'
367
        header_end = "</h5>"
368
        text = line[3:]
369
    elif line.find("[M]") != -1:
370
        text = line[3:]
371
    if center:  # Centuries Text If Condition Is True For Manual Centering
372
        header_start = "<center>" + header_start
373
        header_end += "</center>"
374
    if text.find("[center]") != -1:  # Find Center Tag In Each Line
375
        header_start = "<center>" + header_start
376
        header_end += "</center>"
377
        text = text[:text.find("[center]")]
378
    return [text, header_end, header_start]
379
380
381
def print_text(text_file, file, center=False, close=False):  # Write Text Part Of Each Page
382
    """Write the text part of each page
383
384
    :param text_file: Text tha should be written.
385
    :param file     : The file that text will be written inside.
386
    :param center   : put the text in center.
387
    :param close    : close file after done editing
388
389
    :type close : bool
390
    :type center: bool
391
392
    """
393
394
    text_code = ""
395
    for line in text_file:
396
        if len(line) == 1:
397
            text_code = space
398
        else:
399
            text_header = LSM_translate(line, center)
400
            text = text_header[0]
401
            header_end = text_header[1]
402
            header_start = text_header[2]
403
            text_code = header_start + text + header_end + "\n"
404
        file.write(text_code)
405
    if close:
406
        file.close()
407
408
409
def print_image(file, image_format="jpg", close=False):
410
    """Write Image Part OF The Page.
411
412
    :param file: The file that images will be added.
413
    :param close : close file after done editing.
414
    :param image_format: the format of image
415
416
    :type close : bool
417
    """
418
    for i,item in enumerate(size_box):
419
        print(i, "-", item)
420
    image_size = int(input("Please Enter Profile Image Size : "))  # Choose Profile Image Size
421
    image_size_string = size_box[2]  # Getting Html String From size_box list default mode (Medium)
422
    if 0 <= image_size < len(size_box):
423
        image_size_string = size_box[image_size]
424
    image_code = '<center><img src="image.' + image_format + '"' + ', width=' + image_size_string + ' alt="profile image"></img></center>\n'
425
    file.write(image_code)
426
    if close:
427
        file.close()
428
429
430
def print_download(file, name, link, center=False, close=False):
431
    """ Create Download Link in page
432
433
    :param file: The file that contain html of page.
434
    :param name: The name of the link
435
    :param link: The place that name is Linked
436
    :param center: put the text in center
437
    :param close : close file after done editing
438
439
    :type center: bool
440
    :type close : bool
441
442
    """
443
    link_code = "<a href=" + '"' + link + '"' + target_blank + '>' + name + "</a>"
444
    if center:
445
        link_code = "<center>" + link_code + "</center>"
446
    file.write(link_code + "\n")
447
    file.write(break_line)
448
    if close:
449
        file.close()
450
451
452
def print_adv(file, close=True):
453
    """ Print the advertisement.
454
455
    :param file  : The file that should ad to it.
456
    :param close : Close file after add ad
457
    """
458
    file.write(break_line)
459
    file.write(
460
        '<center>' + "<p>" + "Generated " + today_time + " By" + "</p>" + '<a href=' + '"' + homepage + '"' + target_blank + '>' + '<img src="' + create_badge(
461
            random=True) + '"alt="Qpage">' + '</a> </center>')
462
    if close:
463
        file.close()
464
465
466
def build_index(file):
467
    """ Find and build index page
468
469
    :param file: The index file.
470
    """
471
    image_name = ""
472
    img_format = "jpg"
473
    file_of_images = os.listdir(image_dir)
474
    for i in file_of_images:
475
        for form in imformat_box:
476
            if i.find("." + form) != -1:
477
                image_name = os.path.join(image_dir, i)
478
                img_format = form
479
                global image_counter
480
                image_counter = 1
481
                break
482
    shutil.copyfile(image_name, os.path.join(out_dir, "image." + img_format))
483
    print_image(file, img_format)
484
485
486
def build_resume(file):
487
    """ Find and build resume page.
488
489
    :param file: The resume file.
490
    """
491
    resume_name = ""
492
    file_of_docs = os.listdir(doc_dir)
493
    for i in file_of_docs:
494
        if i.find(".pdf") != -1:
495
            resume_name = os.path.join(doc_dir, i)
496
            global pdf_counter
497
            pdf_counter = 1
498
            break
499
    shutil.copyfile(resume_name, os.path.join(out_dir, "Resume.pdf"))
500
    print_download(file, "Download Full Version", "Resume.pdf", center=True)
501
502
503
def contain(name):
504
    """main function That Open Each Page HTML File and call other function to write data in it
505
506
    :param name: the name of the file that should be written
507
    """
508
    #
509
    file = open(os.path.join(out_dir, name + ".html"), "a")
510
    text_file = open(os.path.join(doc_dir, name + ".txt"), "r")
511
    files.append(file)
512
    files.append(text_file)
513
514
    if name.upper() == "INDEX":
515
        build_index(file)
516
    elif name.upper() == "RESUME":
517
        build_resume(file)
518
519
    print_text(text_file, file)
520
    if name.upper() == "INDEX":
521
        print_adv(file)
522
523
524
def clear_folder(path):
525
    """This Function Get Path Of Foldr And Delete Its Contains
526
527
    :param path: the path that gonna be deleted.
528
    """
529
530
    if os.path.exists(path):
531
        list_of_files = os.listdir(path)
532
        for file in list_of_files:
533
            os.remove(os.path.join(path, file))
534
    else:
535
        os.mkdir(path)
536
537
538
def print_warning():
539
    """ Print Warinigns!
540
541
    """
542
    print(str(len(warnings)) + " Warning , 0 Error")
543
    for i,item in enumerate(warnings):
544
        print(str(i + 1) + "-" + item)
545
546
547
def get_color_code():
548
    """Ask for selecting color of text and background
549
550
    :return list: background and text color
551
    """
552
    for i,item in enumerate(color_box):
553
        print(i, "-", item)
554
    back_color_code = int(input("Please enter your background color : "))
555
    if back_color_code not in range(7):
556
        back_color_code = 0
557
    text_color_code = int(input("Please enter your text color : "))
558
    if text_color_code not in range(7):
559
        text_color_code = 1
560
    return [back_color_code, text_color_code]
561
562
563
def color_code_map():
564
    """ Check and insert colors that is chosen.
565
566
    :return list: background and text color
567
    """
568
    [back_color_code, text_color_code] = get_color_code()
569
    if text_color_code == back_color_code:
570
        warnings.append(warning_dict["color_warning"] + " Your text color and background color are same!!")
571
    background_color = color_box[back_color_code]  # convert code to color string in color_box
572
    text_color = color_box[text_color_code]  # convert code to color string in color_box
573
    return [background_color, text_color]
574
575
576
def css_font(font_folder):
577
    """ Search and file all fonts.
578
579
    :param font_folder: the folder to search.
580
    :return list : font_flag and the current format
581
    """
582
    font_flag = 0  # 0 If there is no font file in font_folder
583
    current_font_format = None
584
    for i in font_folder:
585
        for j in font_format:  # search for other font format in font box
586
            if i.lower().find(j) != -1:  # If there is a font in font folder
587
                shutil.copyfile(os.path.join(font_dir, i),
588
                                os.path.join(out_dir, "qpage" + j))  # copy font file to output folder
589
                font_flag = 1  # Turn Flag On
590
                current_font_format = j  # font format of current selected font for css editing
591
    return [font_flag, current_font_format]
592
593
594
def font_creator(css_file, font_section):
595
    """ Ask and Select font.
596
597
    :param css_file: the file that font css will be added to.
598
    :param font_section: the font section of css file
599
600
    :return font_section: the font section of css after edit
601
    """
602
    font_folder = os.listdir(font_dir)
603
    details = css_font(font_folder)
604
    current_font_format = details[1]
605
    font_flag = details[0]
606
607
    if font_flag == 1:  # check flag if it is 1
608
        css_file.write(
609
            "@font-face{\nfont-family:qpagefont;\nsrc:url(qpage"
610
            + current_font_format
611
            + ");\n}\n")  # Write font-face in html
612
613
        font_section = "font-family:qpagefont;\n"  # Update Font Section For Body Tag
614
        for i,item in enumerate(fontstyle_box):
615
            print(i, "-", item)
616
        font_style = int(input(" Please choose your font style "))
617
        if font_style < len(fontstyle_box):
618
            font_style = fontstyle_box[font_style]
619
        else:
620
            font_style = "normal"
621
        font_section = font_section + "font-style:" + font_style + ";\n"
622
    else:
623
        warnings.append(warning_dict["font_warning"] + " There is no specific font set for this website!!")
624
    return font_section
625
626
627
def css_creator():
628
    """Ask For background and text color in and make css """
629
    font_section = 'font-family : Georgia , serif;\n'
630
    colors = color_code_map()
631
    background_color = colors[0]
632
    text_color = colors[1]
633
634
    css_file = open(os.path.join(out_dir, "styles.css"), "w")  # open css file
635
    font_section = font_creator(css_file, font_section)
636
637
    css_file.write(
638
        ".body_tag{\n"
639
        + "background-color:"
640
        + background_color
641
        + ";\n"
642
        + font_section
643
        + css_margin
644
        + css_animation_1
645
        + "}\n")  # write body tag
646
647
    css_file.write(".color_tag{\n" + "color:" + text_color + ";\n}")  # write color_tag in css
648
    css_file.write(css_animation_2)
649
    css_file.close()  # close css file
650
651
652
def preview():
653
    """Preview website in browser """
654
    # TODO: not working on unix
655
656
    webbrowser.open(os.path.join(out_dir, "index.html"))
657
658
659
def error_finder():
660
    """ Check and find error that display it"""
661
    error_vector = []
662
    pass_vector = []
663
    pdf_counter = 0
664
    #image_list = os.listdir(image_dir)
665
    doc_list = os.listdir(doc_dir)
666
    if image_counter == 1:
667
        pass_vector.append("[Pass] Your profile image in OK!!")
668
    else:
669
        error_vector.append(error_dict["image_error"] + " Your profile image is not in correct format")
670
    if len(doc_list) == 0:
671
        error_vector.append(error_dict["empty_error"] + "There is no file in doc folder ( index.txt and .pdf file in "
672
                                                        "necessary)")
673
    else:
674
        if "index.txt" in doc_list:
675
            pass_vector.append("[Pass] index.txt file OK!")
676
        else:
677
            error_vector.append(error_dict["firstpage_error"] + " index.txt is not in doc folder!")
678
        if pdf_counter == 0:
679
            error_vector.append(error_dict["resume_error"] + "[Error] Where Is Your Resume File? It should be in doc "
680
                                                             "folder")
681
        else:
682
            pass_vector.append("[Pass] Your Resume File is OK!!")
683
    return [error_vector, pass_vector]
684
685
686
def icon_creator():
687
    """ Find .ico file and use it as favicon of website."""
688
    icon_flag = 0
689
    for file in os.listdir(image_dir):
690
        if file.endswith('ico'):
691
            shutil.copy(os.path.join(image_dir, file), out_dir)
692
            os.rename(os.path.join(out_dir, file), os.path.join(out_dir, 'favicon.ico'))
693
            icon_flag = 1
694
            break
695
    if "favicon.ico" in os.listdir(work_dir) and icon_flag == 0:
696
        shutil.copy(os.path.join(work_dir, "favicon.ico"), out_dir)
697
        warnings.append(warning_dict["icon_warning"] + " There is no icon for this website")
698
699
700
def robot_maker():
701
    """ Create Robots.txt for pages """
702
    robots = open(os.path.join(out_dir, "robots.txt"), "w")
703
    robots.write("User-agent: *\n")
704
    robots.write("Disallow: ")
705
    robots.close()
706
707
708
def internet(host="8.8.8.8", port=53, timeout=3):
709
    """ Check Internet Connections.
710
711
    :param  host: the host that check connection to
712
    :param  port: port that check connection with
713
    :param  timeout: times that check the connnection
714
715
    :return bool: True if Connection is Stable
716
    """
717
    try:
718
        socket.setdefaulttimeout(timeout)
719
        socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
720
        return True
721
    except Exception as ex:
722
        print(ex)
723
        return False
724
725
726
def server():
727
    """Get Server response."""
728
    #global meta_input
729
    headers = {'content-type': 'application/json', "NAME": meta_input, "Version": version, "SYSTEM": system_details(),
730
               "IP": find_global_ip()}
731
    response = requests.get(server_api, headers=headers)
732
    if response.status_code==200:
733
        print("Installed Saved!")
734
735
736
def version_control():
737
    """ Check and update Versions. """
738
739
    try:
740
        # print("Check for new version . . .")
741
        # print_line(70)
742
        version_pattern = r"last_version:(.+)"
743
        if internet():
744
            response = requests.get("http://www.qpage.ir/releases.html")
745
            body = response.text
746
            last_version = float(re.findall(version_pattern, body)[0][:-3])
747
            if last_version > float(version):
748
                print_line(70)
749
                print("**New Version Of Qpage Is Available Now (Version " + str(last_version) + ")**")
750
                print("Download Link -->" + "https://github.com/sepandhaghighi/qpage/archive/v" + str(
751
                    last_version) + ".zip")
752
                print_line(70)
753
            else:
754
                # TODO : fix version control else
755
                pass
756
                # print("Already Updated!!!")
757
                # print_line(70)
758
    except:
759
        pass
760
761
762
def enter_to_exit():
763
    """Quit Project by pressing a key.
764
765
    """
766
767
    print_line(70, "*")
768
    response = input("Enter [R] for restart Qpage and any other key to exit : ")
769
    if response.upper() != "R":
770
        sys.exit()
771
772
773
def wait_func(iteration):
774
    """Wait for-in range Iteration.
775
776
    :param iteration: the amount of wait.
777
    """
778
779
    for _ in range(iteration):
780
        time.sleep(1)
781
        print(".")
782