wait_func()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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