Completed
Push — master ( 9ae8e3...960cec )
by Sepand
01:03
created

error_log()   A

Complexity

Conditions 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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