-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathsetup.py
1796 lines (1667 loc) · 84.7 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
'''
_______
| \ \ / @@@;
| \ \ / `#....@
| | \ / ,;@.....;,;
| | \ / @..@........@` PyWeather Setup
| | \ / .............@ version 0.6.3 beta
| / \ / .............@ (c) 2017-2018 - o355
|_______/ | @...........#`
| | .+@@++++@#;
| | @ ; ,
| | : ' .
| | @ # .`
| | @ # .`
'''
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
if sys.version_info < (3, 0, 0):
print("You'll need Python 3 to run PyWeather.",
"Press enter to exit.")
input()
sys.exit()
elif (sys.version_info > (3, 0, 0)
and sys.version_info < (3, 5, 0)):
print("You have a Python version between 3.0 and 3.4.",
"While PyWeather will work, you may experience a few quirks.",
"Try updating to Python 3.6, as it works more reliably.",
"Please take note of this in PyWeather.","", sep="\n")
elif sys.version_info >= (3, 7, 0):
print("You have a Python version of 3.7 and greater.",
"Please note that PyWeather 0.6.2 beta is NOT certified to work with",
"Python 3.7. Python 3.6 and below should work just fine.", sep="\n")
import configparser
import traceback
import subprocess
import logging
import os
import urllib
# Now force the writing of the versioninfo file during setup, this should prevent issues
# in the event I forget to gitignore the file.
try:
open('updater//versioninfo.txt', 'w').close()
with open("updater//versioninfo.txt", 'a') as out:
out.write("0.6.3 beta")
out.close()
except:
print("Couldn't write the versioninfo file. This may cause issues with PyWeather down the road.")
config = configparser.ConfigParser()
config.read('storage//config.ini')
def configprovision():
try:
config.add_section("GEOCODER API")
except configparser.DuplicateSectionError:
print("Failed to add the Geocoder API section.")
try:
config.add_section("FAVORITE LOCATIONS")
except configparser.DuplicateSectionError:
print("Failed to add the favorite locations section.")
try:
config.add_section("HURRICANE")
except configparser.DuplicateSectionError:
print("Failed to add the hurricane section.")
try:
config.add_section("FIRSTINPUT")
except configparser.DuplicateSectionError:
print("Failed to add the firstinput section.")
try:
config.add_section('SUMMARY')
except configparser.DuplicateSectionError:
print("Failed to add the summary section.")
try:
config.add_section('VERBOSITY')
except configparser.DuplicateSectionError:
print("Failed to add the verbosity section.")
try:
config.add_section('TRACEBACK')
except configparser.DuplicateSectionError:
print("Failed to add the traceback section.")
try:
config.add_section('UI')
except configparser.DuplicateSectionError:
print("Failed to add the UI section.")
try:
config.add_section('PREFETCH')
except configparser.DuplicateSectionError:
print("Failed to add the prefetch section.")
try:
config.add_section('UPDATER')
except configparser.DuplicateSectionError:
print("Failed to add the updater section.")
try:
config.add_section('KEYBACKUP')
except configparser.DuplicateSectionError:
print("Failed to add the keybackup section.")
try:
config.add_section('PYWEATHER BOOT')
except configparser.DuplicateSectionError:
print("Failed to add the PyWeather Boot section.")
try:
config.add_section('USER')
except configparser.DuplicateSectionError:
print("Failed to add the user section.")
try:
config.add_section('CACHE')
except configparser.DuplicateSectionError:
print("Failed to add the cache section.")
try:
config.add_section('RADAR GUI')
except configparser.DuplicateSectionError:
print("Failed to add the Radar GUI section.")
try:
config.add_section('GEOCODER')
except configparser.DuplicateSectionError:
print("Failed to add the Geocoder section.")
config['SUMMARY']['sundata_summary'] = 'False'
config['SUMMARY']['almanac_summary'] = 'False'
config['SUMMARY']['showalertsonsummary'] = 'True'
config['SUMMARY']['showtideonsummary'] = 'False'
config['SUMMARY']['showyesterdayonsummary'] = 'False'
config['VERBOSITY']['verbosity'] = 'False'
config['VERBOSITY']['json_verbosity'] = 'False'
config['VERBOSITY']['setup_verbosity'] = 'False'
config['VERBOSITY']['setup_jsonverbosity'] = 'False'
config['VERBOSITY']['updater_verbosity'] = 'False'
config['VERBOSITY']['updater_jsonverbosity'] = 'False'
config['VERBOSITY']['keybackup_verbosity'] = 'False'
config['VERBOSITY']['configdefault_verbosity'] = 'False'
config['TRACEBACK']['tracebacks'] = 'False'
config['TRACEBACK']['setup_tracebacks'] = 'False'
config['TRACEBACK']['updater_tracebacks'] = 'False'
config['TRACEBACK']['configdefault_tracebacks'] = 'False'
config['UI']['show_entertocontinue'] = 'True'
config['UI']['detailedinfoloops'] = '6'
config['UI']['forecast_detailedinfoloops'] = '5'
config['UI']['show_completediterations'] = 'False'
config['UI']['alerts_usiterations'] = '1'
config['UI']['alerts_euiterations'] = '2'
config['UI']['extratools_enabled'] = 'False'
config['PREFETCH']['10dayfetch_atboot'] = 'False'
config['PREFETCH']['yesterdaydata_atboot'] = 'False'
config['UPDATER']['autocheckforupdates'] = 'False'
config['UPDATER']['show_updaterreleasetag'] = 'False'
config['KEYBACKUP']['savedirectory'] = 'backup//'
config['PYWEATHER BOOT']['validateapikey'] = 'True'
config['UPDATER']['showReleaseNotes'] = 'True'
config['UPDATER']['showReleaseNotes_uptodate'] = 'False'
config['UPDATER']['showNewVersionReleaseDate'] = 'True'
config['USER']['configprovisioned'] = 'True'
config['CACHE']['enabled'] = 'True'
config['CACHE']['alerts_cachedtime'] = '5'
config['CACHE']['current_cachedtime'] = '10'
config['CACHE']['threedayhourly_cachedtime'] = '60'
config['CACHE']['tendayhourly_cachedtime'] = '60'
config['CACHE']['forecast_cachedtime'] = '60'
config['CACHE']['almanac_cachedtime'] = '240'
config['CACHE']['sundata_cachedtime'] = '480'
config['CACHE']['tide_cachedtime'] = '480'
config['CACHE']['hurricane_cachedtime'] = '180'
config['CACHE']['yesterday_cachedtime'] = '720'
config['RADAR GUI']['radar_imagesize'] = 'normal'
config['RADAR GUI']['bypassconfirmation'] = 'False'
config['GEOCODER']['scheme'] = 'https'
config['GEOCODER API']['customkey_enabled'] = 'False'
config['GEOCODER API']['customkey'] = 'None'
config['PREFETCH']['hurricanedata_atboot'] = 'False'
config['FIRSTINPUT']['geoipservice_enabled'] = 'False'
config['FIRSTINPUT']['allow_pwsqueries'] = 'True'
config['HURRICANE']['enablenearestcity'] = 'False'
config['HURRICANE']['enablenearestcity_forecast'] = 'False'
config['HURRICANE']['api_username'] = 'pyweather_proj'
config['HURRICANE']['nearestcitysize'] = 'medium'
config['FAVORITE LOCATIONS']['enabled'] = 'True'
config['FAVORITE LOCATIONS']['favloc1'] = 'None'
config['FAVORITE LOCATIONS']['favloc2'] = 'None'
config['FAVORITE LOCATIONS']['favloc3'] = 'None'
config['FAVORITE LOCATIONS']['favloc4'] = 'None'
config['FAVORITE LOCATIONS']['favloc5'] = 'None'
try:
with open('storage//config.ini', 'w') as configfile:
config.write(configfile)
except:
print("Hmm...an odd error occurred. A full traceback will be",
"printed below. Please report this issue on GitHub",
"(github.com/o355/pyweather), as that would be greatly appreciated",
"for trying to fix the bug that you just encountered!", sep="\n")
traceback.print_exc()
# Giving users choice, unlike Microsoft.
print("Would you like to continue using PyWeather with an unprovisioned config?",
"It's highly recommended you don't continue, as you may encounter",
"unexpected errors and issues with using PyWeather. Yes or No.", sep="\n")
provisionfailed_continue = input("Input here: ").lower()
if provisionfailed_continue == "yes":
print("Continuing with PyWeather Setup. Please remember, you may encounter",
"unexpected errors and issues. You can always retry provisioning your config",
"by using the configsetup.py script in the storage folder.", sep="\n")
elif provisionfailed_continue == "no":
print("Stopping PyWeather Setup. You can retry to provision your config by using",
"the configsetup.py script in the storage folder.",
"Press enter to exit.", sep="\n")
input()
sys.exit()
else:
print("Couldn't understand your input. By default, PyWeather Setup is stopping.",
"You can retry to provision your config by using the configsetup.py script",
"in the storage folder. Press enter to exit.", sep="\n")
input()
sys.exit()
# See if the config is "provisioned". If it isn't, a KeyError will occur,
# because it's not created. Here, we set up the config to defaults if it's not
# provisioned.
try:
configprovisioned = config.getboolean('USER', 'configprovisioned')
except:
print("Your config likely isn't provisioned. Would you like to provision your config?",
"It's highly recommended you provision your config. If you decide not to,",
"you may run into issues using PyWeather.",
"Yes or No.", sep="\n")
provisionconfig = input("Input here: ").lower()
if provisionconfig == "yes":
print("Provisioning your config.")
configprovision()
print("Config file provisioned successfully! Moving on with PyWeather setup...")
elif provisionconfig == "no":
print("Not provisioning your config. You may encounter unexpected errors",
"and issues when using PyWeather, however.", sep="\n")
else:
print("Couldn't understand your input. By default, your configuration will",
"be provisioned.", sep="\n")
configprovision()
print("Config file provisioned successfully! Moving on with PyWeather setup...")
try:
verbosity = config.getboolean('VERBOSITY', 'setup_verbosity')
jsonVerbosity = config.getboolean('VERBOSITY', 'setup_jsonverbosity')
tracebacksEnabled = config.getboolean('TRACEBACK', 'setup_tracebacks')
except:
print("Couldn't load your config file. Make sure there aren't any typos",
"in the config, and that the config file is accessible.",
"Setting config variables to their defaults.",
"Here's the full traceback, in case you need it.", sep="\n")
traceback.print_exc()
verbosity = False
jsonVerbosity = False
tracebacksEnabled = False
def printException():
if tracebacksEnabled == True:
print("Here's the full traceback (for error reporting):")
traceback.print_exc()
def printException_loggerwarn():
if verbosity == True:
logger.warning("Oh snap! We ran into a non-critical error. Here's the traceback.")
traceback.print_exc()
logger = logging.getLogger(name='pyweather_setup_0.6.2beta')
logger.setLevel(logging.DEBUG)
logformat = '%(asctime)s | %(levelname)s | %(message)s'
logging.basicConfig(format=logformat)
if verbosity == True:
logger.setLevel(logging.DEBUG)
elif tracebacksEnabled == True:
logger.setLevel(logging.ERROR)
else:
logger.setLevel(logging.CRITICAL)
logger.debug("Listing configuration options:")
logger.debug("verbosity: %s ; jsonVerbosity: %s" %
(verbosity, jsonVerbosity))
logger.debug("tracebacksEnabled: %s" %
tracebacksEnabled)
print("Hi! Welcome to PyWeather 0.6.3 beta! Glad that you're here.",
"This setup script will set up PyWeather, and let you configure it to your liking.",
"Let's begin!", sep="\n")
import shutil
import time
import json
import codecs
buildnumber = 63
buildversion = "0.6.3 beta"
logger.debug("buildnumber: %s ; buildversion: %s" %
(buildnumber, buildversion))
print("","Before we get started, let's want to confirm some permissions from you.",
"Is it okay if 1-5 MB of data (downloading libraries) is used, very small",
"text files (apikey.txt & backkey.txt) are created, and Python libraries are",
"automatically installed?",
"Please input yes or no below:", sep="\n")
confirmPermissions = input("Input here: ").lower()
logger.debug("confirmPermissions: %s" % confirmPermissions)
if confirmPermissions == "no":
logger.debug("User denied permissions. Closing...")
print("Cannot continue without your consent. Closing PyWeather Setup.",
"Press enter to exit.", sep="\n")
input()
sys.exit()
elif confirmPermissions != "yes":
logger.debug("Couldn't understand. Closing...")
print("Your input was not understood. Closing PyWeather Setup as a precaution.",
"You can always relaunch this script at any time. Press enter to exit.", sep="\n")
input()
sys.exit()
print("","Cool! Let's start.",
"Now checking for necessary libraries (to run PyWeather).",
"This can take a moment, so please wait for just a moment.", sep="\n")
try:
import pip
except ImportError:
logger.warn("pip is NOT installed! Asking user for automated install...")
printException_loggerwarn()
print("", "Shucks! pip couldn't be imported, and pip is needed to install",
"libraries for you. Would you like pip to be installed for you?",
"Yes or No.", sep="\n")
pipConfirm = input("Input here: ").lower()
logger.debug("pipConfirm: %s" % pipConfirm)
if pipConfirm == "no":
logger.info("User denied pip install, closing...")
print("", "pip is needed to continue with PyWeather Setup. As such, PyWeather",
"Setup will now be closed. Press enter to exit.", sep="\n")
input()
sys.exit()
elif pipConfirm == "yes":
logger.info("User allowed PIP install. Starting...")
print("Now downloading the pip install script in 5 seconds.",
"This should use 2-4 MB of data, and will quit PyWeather Setup",
"when complete. After PyWeather Setup quits, please relaunch PW Setup.",
"If you'd like to cancel the download, press Ctrl + C in the next 5 seconds.", sep="\n")
try:
time.sleep(5)
except KeyboardInterrupt:
print("You cancelled the pip install. pip is required to continue with",
"PyWeather Setup, and will now be closed. Press enter to exit.", sep="\n")
input()
sys.exit()
print("Downloading the installer...")
# We use the built-in urllib library, as some Python installs don't include requests.
try:
with urllib.request.urlopen('https://bootstrap.pypa.io/get-pip.py') as update_response, open('get-pip.py',
'wb') as update_out_file:
logger.debug("update_response: %s ; update_out_file: %s"
% (update_response, update_out_file))
shutil.copyfileobj(update_response, update_out_file)
except:
print("Couldn't download the pip installer, either due to no internet or a library failure.",
"As an alternative, you can download the installer yourself. Please download:",
"'https://bootstrap.pypa.io/get-pip.py', and put it in PyWeather's base directory.",
"When you're done, press enter to install pip, or press Ctrl + C to quit setup.", sep="\n")
printException()
try:
input()
except:
print("You cancelled the pip install. pip is required to continue with",
"PyWeather Setup, and will now be closed. Press enter to exit.", sep="\n")
input()
sys.exit()
print("Running the installer...")
logger.debug("Executing get-pip.py. If this script exits, please restart the setup script.")
exec(open("get-pip.py").read())
else:
logger.warning("Couldn't understand the input. Closing...")
print("", "Your input was not understood. As a precation, PyWeather Setup",
"will be closed, as pip is required to continue with setup.",
"Press enter to exit.", sep="\n")
input()
sys.exit()
except PermissionError:
traceback.print_exc()
print("PIP has incorrect permissions on your machine. Please attempt to fix",
"permissions on the folder that is listed in the traceback.",
"Linux users: Use sudo chown -R <yourusername> <folder>, this should fix the issue.",
"Press enter to exit.", sep="\n")
input()
sys.exit()
print("Cleaning up pip installer files (if pip was installed)")
try:
os.remove("get-pip.py")
except:
printException_loggerwarn()
neededLibraries = 0
try:
import colorama
coloramaInstalled = True
logger.info("Colorama is installed.")
logger.debug("coloramaInstalled: %s" % coloramaInstalled)
except ImportError:
coloramaInstalled = False
neededLibraries = neededLibraries + 1
logger.warn("Colorama is not installed.")
printException_loggerwarn()
logger.debug("coloramaInstalled: %s ; neededLibraries: %s"
% (coloramaInstalled, neededLibraries))
try:
import geopy
geopyInstalled = True
logger.info("geopy is installed.")
logger.debug("geopyInstalled: %s" % geopyInstalled)
except ImportError:
geopyInstalled = False
neededLibraries = neededLibraries + 1
logger.info("geopy is NOT installed.")
printException_loggerwarn()
logger.debug("geopyInstalled: %s ; neededLibraries: %s"
% (geopyInstalled, neededLibraries))
try:
from appJar import gui
appjarInstalled = True
logger.info("appjar is installed.")
logger.debug("appjarInstalled: %s" % appjarInstalled)
except ImportError as e:
if e == "No module named '_tkinter', please install the python3-tk package":
print("It appears as if you've already installed appJar, the library for the radar GUI.",
"However, you'll also need to install `python3-tk` using your preferred package",
"manager.", sep="\n")
appjarInstalled = True
logger.debug("appjarInstalled: %s" % appjarInstalled)
else:
appjarInstalled = False
neededLibraries = neededLibraries + 1
logger.debug("appJar is NOT installed.")
printException_loggerwarn()
logger.debug("appjarInstalled: %s ; neededLibraries: %s" %
(appjarInstalled, neededLibraries))
try:
import requests
requestsInstalled = True
logger.debug("requests is installed.")
logger.debug("requestsInstalled: %s" % requestsInstalled)
except:
requestsInstalled = False
neededLibraries = neededLibraries + 1
logger.debug("requests is NOT installed.")
printException_loggerwarn()
logger.debug("requestsInstalled: %s ; neededLibraries: %s" %
(requestsInstalled, neededLibraries))
try:
import halo
haloInstalled = True
logger.debug("halo is installed.")
logger.debug("haloInstalled: %s" % haloInstalled)
except:
haloInstalled = False
neededLibraries += 1
logger.debug("halo is NOT installed.")
printException_loggerwarn()
logger.debug("haloInstalled: %s ; neededLibraries: %s" %
(haloInstalled, neededLibraries))
try:
import click
clickInstalled = True
logger.debug("click is installed.")
logger.debug("clickInstalled: %s" % clickInstalled)
except:
clickInstalled = False
neededLibraries += 1
logger.debug("click is NOT installed.")
printException_loggerwarn()
logger.debug("clickInstalled: %s ; neededLibraries: %s" %
(haloInstalled, neededLibraries))
print("All done!")
if neededLibraries == 0:
logger.debug("All libraries are installed.")
print("All necessary libraries have been installed!")
else:
logger.debug("Libraries need to be installed.")
print("Not all necessary libraries are installed. Here's what needs to be installed:")
if coloramaInstalled is False:
print("- Colorama")
if geopyInstalled is False:
print("- Geopy")
if appjarInstalled is False:
print("- appJar")
if requestsInstalled is False:
print("- Requests")
if haloInstalled is False:
print("- Halo")
if clickInstalled is False:
print("- Click")
print("Would you like these libraries to be automatically installed for you?",
"Yes or No.", sep="\n")
neededLibrariesConfirm = input("Input here: ").lower()
logger.debug("neededLibrariesConfirm: %s" % neededLibrariesConfirm)
if neededLibrariesConfirm == "no":
logger.warning("Not installing necessary libraries. Now exiting...")
print("To continue with PyWeather Setup, necessary libraries need to be installed.",
"Press enter to exit.")
input()
sys.exit()
elif neededLibrariesConfirm == "yes":
print("Now installing necessary libraries...")
if coloramaInstalled is False:
print("Installing Colorama...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'colorama'])
if geopyInstalled is False:
print("Installing geopy...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'geopy'])
if appjarInstalled is False:
print("Installing appJar...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'appjar'])
if requestsInstalled is False:
print("Installing requests...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'requests'])
if haloInstalled is False:
print("Installing halo...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'halo'])
if clickInstalled is False:
print("Installing click...")
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'click'])
logger.info("Running the double check on libraries...")
print("Sweet! All libraries should be installed.",
"Now checking if all libraries are installed properly.", sep="\n")
try:
import colorama
logger.info("Colorama installed successfully.")
except ImportError:
logger.warn("colorama was not installed successfully.")
printException()
print("Colorama did not install properly. Please try attempting to",
"install Colorama in a command prompt by using the command",
"`pip3 install colorama`. Press enter to exit.")
input()
sys.exit()
try:
import geopy
logger.info("geopy installed successfully.")
except ImportError:
logger.warn("geopy was not installed successfully.")
printException()
print("Geopy did not install properly. Please try attempting to",
"install Geopy in a command prompt by using the command",
"`pip3 install geopy`. Press enter to exit.")
input()
sys.exit()
# appJar is skipped here as to avoid issues on non-GUI platforms.
# Full support for appJar checking may eventually come.
try:
import requests
logger.info("requests installed successfully.")
except ImportError:
logger.warning("Requests was not installed successfully.")
printException()
print("Requests did not install properly. Please try attempting to",
"install Requests in a command prompt by using the command",
"`pip3 install requests`. Press enter to exit.")
input()
sys.exit()
try:
import halo
logger.info("Halo installed successfully.")
except ImportError:
logger.warn("halo was not installed successfully.")
printException()
print("Halo did not install properly. Please try attempting to",
"install Halo in a command prompt by using the command",
"`pip3 install halo`. Press enter to exit.")
input()
sys.exit()
try:
import click
logger.info("Click installed successfully.")
except ImportError:
logger.warning("Click was not installed successfully.")
printException()
print("Click did not install properly. Please try attempting to",
"install Geopy in a command prompt by using the command",
"`pip3 install click`. Press enter to exit.")
input()
sys.exit()
print("","All libraries are installed!", sep="\n")
else:
logger.warn("Input was not understood. Closing...")
print("Your input wasn't understood. As a precaution, PyWeather Setup will now close.",
"Necessary libraries are required to continue with setup. Press enter to exit.", sep="\n")
input()
sys.exit()
# Previously this updated all your pip packages. I then did this on my NAS (on FreeNAS 11).
# It broke my NAS! Woo hoo!
print("", "Would you like to automatically update PyWeather's required libraries?",
"Doing this is generally recommended, and will have benefits down the line when",
"some libraries fix known issues that occur in PyWeather. Yes or No.", sep="\n")
confirm_updatepip = input("Input here: ").lower()
logger.debug("confirm_updatepip: %s" % confirm_updatepip)
if confirm_updatepip == "yes":
print("")
print("Updating PIP packages.")
totalpackages = 5
updatecount = 1
pip_requiredlibraries = ['requests', 'halo', 'appjar', 'colorama', 'geopy', "click"]
for pkgname in pip_requiredlibraries:
print("Now updating package: %s (Update %s/%s)" %
(pkgname, updatecount, totalpackages))
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', '%s' % pkgname])
updatecount = updatecount + 1
elif confirm_updatepip == "no":
print("Not updating PIP packages. You may run into issues with non-updated",
"packages in future versions of PyWeather.")
else:
print("Input not understood, not updating PIP packages. You may run into",
"issues with non-updated packages in future versions of PyWeather.")
# Verbosity is not needed here.
print("Let's guide you through obtaining an API key.",
"Please carefully read my detailed instructions, so you don't mess anything up.", sep="\n")
print("","If you know how to acquire a Wunderground API key, or are resetting PyWeather,",
"hit enter 14 times to get to the API key entry.", sep="\n")
print("Let's begin.",
"Start by opening a web browser, and going to https://www.wunderground.com/weather/api/.",
"Press any key when you are done.", sep="\n")
input()
print("Next, click the 'Explore my options' button.",
"Press any key when you are done.", sep="\n")
input()
print("Next, click the small button next to 'ANVIL PLAN'.",
"After that, confirm that the total underneath the 'Purchase Key' button says",
"'$0 USD per month'.",
"If the total underneath the 'Purchase Key' button doesn't",
"say '$0 USD per month, please ensure that the small button next to 'Developer'",
"on the table in the middle of the screen is selected, and the total",
"says '$0 USD per month'",
"Press any key when you are done.", sep="\n")
input()
print("Next, click the 'Purchase Key' button.",
"Press any key when you are done.", sep="\n")
input()
print("Next, input your email, and a password to sign up for a Weather",
"Underground account.",
"Be sure to select the checkbox next to 'I agree to the Terms of Service'",
"It's best if you leave the checkbox next to 'I would like to receive WU",
"updates via email' unchecked.",
"Press any key when you are done and ready.", sep="\n")
input()
print("Next, press the 'Sign up for free' button.",
"When the welcome window pops up, be sure to click the X button at the top right of the popup.",
"When clicking the X, you should be redirected to wunderground.com.",
"Press any key when you are done and ready.", sep="\n")
input()
print("Next, click 'My Profile' at the top right corner of the homepage.",
"In the dropdown, click 'My Email & Text Alerts'",
"Press any key when you are done and ready.", sep="\n")
input()
print("Next, next to your email listed on the page, click the 'Edit / Verify' button.",
"After you click the button, click the 'Verify Email' button.",
"Press any key when you are done and ready.", sep="\n")
input()
print("Next, check your email in which you signed up with.",
"If you got a letter from Weather Underground, titled 'Daily Forecast",
"Email Verification', open that letter, and click the link.",
"If you didn't get the letter, wait a few minutes, and be sure to check your spam folder.",
"Hint: If you followed this guide exactly, WU will not be sending you daily forecasts to your email.",
"Press any key when you are done and ready.", sep="\n")
input()
print("Your email should be verified.",
"Next, in your web browser, head back to https://www.wunderground.com/weather/api/.",
"Then, click the 'Explore my Options' button, again.",
"Press any key when you are done and ready.", sep="\n")
input()
print("Next, at the top of the page, make sure the button next to 'ANVIL PLAN'",
"is selected.",
"After that, confirm that the total underneath the 'Purchase Key' button says",
"'$0 USD per month'",
"If the total doesn't say that, in the pricing table, make sure the button",
"next to 'Developer' is selected.",
"Press any key when you are done and ready.", sep="\n")
input()
print("Next, click the 'Purchase Key' button, on top of your total (which",
"should be $0 USD per month)",
"Next, fill out the form, considering these tips:",
"For the contact name/email, it's recommended you use your real name",
"(first name last initial is fine).",
"It's also recommended that you use your real email.",
"For the project name, put in something generic, like 'to use a script that",
"uses WU's API', or 'WU API test'. It's up to you.",
"For the project website, put in something generic, like 'google.com', or",
"some other site you feel like having as the project site.",
"For the question 'Where will the API be used', answer Other.",
"For the question 'Will the API be used for commercial use?', answer No.",
"For the question 'Will the API be used for manufacturing mobile chip",
"processing?', answer No.",
"Answer yes if you somehow are manufacturing mobile chip processing. I doubt",
"you are, however.",
"For the country that you are based in, put your location.",
"Before we move on, fill out these forms, and press any key when you are done "
"and ready.", sep="\n")
input()
print("Next, for the brief description, put something like 'using an API key",
"to use a script using Wunderground'.",
"After that, check both boxes at the bottom of the page. Read the ToS if you",
"feel like it.",
"Finally, click 'Purchase Key'.",
"You should land on a page that says 'Edit API Key'.",
"Press any key when you are done and ready.", sep="\n")
input()
print("In the table to the left of the page, copy the text that's under Key ID.",
"(Ctrl+C, right click)",
"Please input your API key into the text entry below.",
"The API key will be saved to storage/apikey.txt, so PyWeather can easily",
"pull it up.",
"Press any key when you are done and ready.", sep="\n")
input()
print("Please input your API key below.")
apikey_input = str(input("Input here: ")).replace(" ","").replace("\n","").replace("\t","")
logger.debug("apikey_input: %s" % apikey_input)
print("", "Just to confirm, the API key you inputted was: " + apikey_input
+ ".", sep="\n")
print("Please double check your input, and confirm in the dialogue below.")
apikey_confirm = input("Is the API key right? Yes or no: ").lower()
logger.debug("apikey_confirm: %s" % apikey_confirm)
if apikey_confirm == "no":
while True:
logger.debug("User now re-entering key...")
print("","Please input your API key below.", sep="\n")
apikey_input = str(input("Input here: ")).replace(" ","").replace("\n","").replace("\t","")
logger.debug("apikey_input: %s" % apikey_input)
print("Just to confirm, the API key you inputted was: " + apikey_input
+ ".")
apikey_confirm = input("Is the API key right? Yes or no: ").lower()
if apikey_confirm == "yes":
break
elif apikey_confirm == "no":
continue
else:
print("Couldn't understand your input.",
"I'll assume the API key is correct, moving on.", sep="\n")
print("Now saving your API key...")
open('storage//apikey.txt', 'w').close()
with open("storage//apikey.txt", 'a') as out:
logger.debug("out: %s" % out)
out.write(apikey_input)
out.close()
logger.debug("Performed ops: overwrite apikey.txt, out.write(apikey_input), out.close()")
print("", "Your API key can be backed up, in case something goes wrong.")
# A future release should bring customization as to the storage location.
print("Would you like me to save a backup? Yes or no.")
backup_APIkey = input("Input here: ").lower()
if backup_APIkey == "yes":
print("Which directory in the PyWeather folder would you like your",
"backup key to be stored in? The default directory is backup.",
"You can also press enter to use the backup directory by default.", sep="\n")
# Doing a .lower() here to prevent case insensitiveness.
backup_APIkeydirectory = input("Input here: ").lower()
folder_argument = backup_APIkeydirectory + "//backkey.txt"
backup_APIkeydirectory2 = backup_APIkeydirectory + "//"
logger.debug("backup_APIkeydirectory: %s ; backup_APIkeydirectory2: %s" %
(backup_APIkeydirectory, backup_APIkeydirectory2))
logger.debug("folder_argument: %s" % folder_argument)
# These two variables will get reset if the directory is backup, or empty.
if backup_APIkeydirectory == "backup" or backup_APIkeydirectory == "":
print("Using the default directory of //backup.")
folder_argument = "backup//backkey.txt"
backup_APIkeydirectory2 = "backup//"
logger.debug("folder_argument: %s ; backup_APIkeydirectory2: %s" %
(folder_argument, backup_APIkeydirectory2))
elif backup_APIkeydirectory != "backup":
try:
os.mkdir(backup_APIkeydirectory2)
except:
printException_loggerwarn()
print("Couldn't make the directory, does it exist?")
# Overwrite the file, if it exists.
open(folder_argument, 'w').close()
open(folder_argument, 'a').write(apikey_input)
open(folder_argument).close()
config['KEYBACKUP']['savedirectory'] = backup_APIkeydirectory2
print("The API key was backed up successfully!")
logger.debug("Performed 3 ops. Overwrite "+ folder_argument + "backkey.txt, write to backkey.txt" +
", and close backkey.txt.")
print("", "Before we configure PyWeather, your API key will be validated.", sep="\n")
# Do an infinite loop of validation of the API key, so the user can reenter the API key
# if it was wrong.
while True:
apitest_URL = 'http://api.wunderground.com/api/' + apikey_input + '/conditions/q/NY/New_York.json'
apitest_URL_https = 'https://api.wunderground.com/api/' + apikey_input + '/conditions/q/NY/New_York.json'
testreader = codecs.getreader("utf-8")
logger.debug("apitest_URL: %s ; apitest_URL_https: %s" % (apitest_URL, apitest_URL_https))
logger.debug("testreader: %s" % testreader)
try:
testJSON = requests.get(apitest_URL_https)
logger.debug("testJSON: %s" % testJSON)
except requests.exceptions.SSLError:
logger.info("Failed to make HTTPS request, making HTTP request instead...")
try:
testJSON = requests.get(apitest_URL)
logger.debug("testJSON: %s" % testJSON)
except:
logger.warning("Couldn't connect to Wunderground's API! No internet?")
print("When PyWeather Setup attempted to fetch the .json to validate your API key,",
"an error occurred. If you're on a network with a filter, make sure that",
"'api.wunderground.com' is unblocked. Otherwise, make sure you have an internet",
"connection.", sep="\n")
printException()
print("Press enter to exit.")
input()
sys.exit()
except:
logger.warning("Couldn't connect to Wunderground's API! No internet?")
print("When PyWeather Setup attempted to fetch the .json to validate your API key,",
"an error occurred. If you're on a network with a filter, make sure that",
"'api.wunderground.com' is unblocked. Otherwise, make sure you have an internet",
"connection.", sep="\n")
printException()
print("Press enter to exit.")
input()
sys.exit()
test_json = json.loads(testJSON.text)
if jsonVerbosity == True:
logger.debug("test_json: %s" % test_json)
try:
test_conditions = str(test_json['current_observation']['temp_f'])
logger.debug("test_conditions: %s" % test_conditions)
print("Hurray! Your API key is valid and works.")
break
except:
logger.warn("Error! Is the API key invalid?")
print("When attempting to validate the API key that you entered/confirmed,",
"PyWeather Setup ran into an error. Would you like to reenter your API key to revalidate it?",
"Please note, that this error might be caused by WU's API being down, or another cause.",
"However, 90% of the time, this is due to a bad API key.",
"Yes or No.", sep='\n')
revalidateAPIkey = input("Input here: ").lower()
if revalidateAPIkey == "yes":
print("Enter in your API key below.")
apikey_input = str(input("Input here: ")).replace(" ","").replace("\n","").replace("\t","")
logger.debug("apikey_input: %s")
print("Revalidating your API key...")
continue
elif revalidateAPIkey == "no":
print("Not revalidating your API key. You'll need a valid API key to continue.",
"Press enter to exit.", sep="\n")
input()
sys.exit()
printException()
print("Press enter to exit.")
input()
sys.exit()
print("Let's configure PyWeather to your liking.")
logger.debug("config: %s" % config)
print("", "(1/42)","On the summary screen, would you like to show sunrise/sunset times?",
"By default, this is disabled.",
"Yes or No.", sep="\n")
sundata_Summary = input("Input here: ").lower()
logger.debug("sundata_Summary: %s" % sundata_Summary)
if sundata_Summary == "yes":
config['SUMMARY']['sundata_summary'] = 'True'
print("Changes saved.")
logger.debug("Sundata on the summary is now ENABLED.")
elif sundata_Summary == "no":
config['SUMMARY']['sundata_summary'] = 'False'
print("Changes saved.")
logger.debug("Sundata on the summary is now DISABLED.")
else:
print("Could not understand what you inputted.",
"Defaulting to 'False'", sep="\n")
config['SUMMARY']['sundata_summary'] = 'False'
print("Changes saved.")
logger.debug("Could not recognize input. Defaulting to DISABLED.")
print("", "(2/42)","On the summary screen, would you like to show almanac data?",
"By default, this is disabled.",
"Yes or no:", sep="\n")
almanacdata_Summary = input("Input here: ").lower()
logger.debug("almanacdata_Summary: %s" % almanacdata_Summary)
if almanacdata_Summary == "yes":
config['SUMMARY']['almanac_summary'] = 'True'
print("Changes saved.")
logger.debug("Almanac on the summary is now ENABLED.")
elif almanacdata_Summary == "no":
config['SUMMARY']['almanac_summary'] = 'False'
print("Changes saved.")
logger.debug("Almanac on the summary is now DISABLED.")
else:
print("Could not understand what you inputted.",
"Defaulting to 'False'", sep="\n")
config['SUMMARY']['almanac_summary'] = 'False'
print("Changes saved.")
logger.debug("Could not recognize input. Defaulting to DISABLED.")
print("", "(3/42)", "On the summary screen, would you like to show alerts data?",
"By default, this is enabled. Please note, Wunderground",
"only supports alert data in the US and EU at this time.",
"Yes or No.", sep="\n")
alertsdata_Summary = input("Input here: ").lower()
logger.debug("alertsdata_Summary: %s" % alertsdata_Summary)
if alertsdata_Summary == "yes":
config['SUMMARY']['showalertsonsummary'] = 'True'
print("Changes saved.")
logger.debug("Alerts on the summary is now ENABLED.")
elif alertsdata_Summary == "no":
config['SUMMARY']['showalertsonsummary'] = 'False'
print("Changes saved.")
logger.debug("Alerts on the summary is now DISABLED.")
else:
print("Could not understand what you inputted.",
"Defaulting to 'True'", sep="\n")
config['SUMMARY']['showAlertsOnSummary'] = 'True'
print("", "(4/42)","On boot, would you like PyWeather to check for updates?",
"By default, this is disabled, due to a load time increase of ~2-5 seconds.",
"Yes or No.", sep="\n")
checkForUpdates = input("Input here: ").lower()
logger.debug("checkForUpdates: %s" % checkForUpdates)
if checkForUpdates == "yes":
config['UPDATER']['autoCheckForUpdates'] = 'True'
print("Changes saved.")
logger.debug("Checking for updates on startup is ENABLED.")
elif checkForUpdates == "no":
config['UPDATER']['autoCheckForUpdates'] = 'False'
print("Changes saved.")
logger.debug("Checking for updates on startup is DISABLED.")
else:
print("Could not understand what you inputted.",
"Defaulting to 'False'", sep="\n")
config['UPDATER']['autoCheckForUpdates'] = 'False'
print("Changes saved.")
logger.debug("Could not recognize input. Defaulting to DISABLED.")
print("", "(5/42)","When an error occurs, would you like PyWeather to show the full error?",