megadetector 5.0.11__py3-none-any.whl → 5.0.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of megadetector might be problematic. Click here for more details.
- megadetector/api/__init__.py +0 -0
- megadetector/api/batch_processing/__init__.py +0 -0
- megadetector/api/batch_processing/api_core/__init__.py +0 -0
- megadetector/api/batch_processing/api_core/batch_service/__init__.py +0 -0
- megadetector/api/batch_processing/api_core/batch_service/score.py +439 -0
- megadetector/api/batch_processing/api_core/server.py +294 -0
- megadetector/api/batch_processing/api_core/server_api_config.py +97 -0
- megadetector/api/batch_processing/api_core/server_app_config.py +55 -0
- megadetector/api/batch_processing/api_core/server_batch_job_manager.py +220 -0
- megadetector/api/batch_processing/api_core/server_job_status_table.py +149 -0
- megadetector/api/batch_processing/api_core/server_orchestration.py +360 -0
- megadetector/api/batch_processing/api_core/server_utils.py +88 -0
- megadetector/api/batch_processing/api_core_support/__init__.py +0 -0
- megadetector/api/batch_processing/api_core_support/aggregate_results_manually.py +46 -0
- megadetector/api/batch_processing/api_support/__init__.py +0 -0
- megadetector/api/batch_processing/api_support/summarize_daily_activity.py +152 -0
- megadetector/api/batch_processing/data_preparation/__init__.py +0 -0
- megadetector/api/batch_processing/integration/digiKam/setup.py +6 -0
- megadetector/api/batch_processing/integration/digiKam/xmp_integration.py +465 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/config_template.py +5 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/push_annotations_to_emammal.py +125 -0
- megadetector/api/batch_processing/integration/eMammal/test_scripts/select_images_for_testing.py +55 -0
- megadetector/api/synchronous/__init__.py +0 -0
- megadetector/api/synchronous/api_core/animal_detection_api/__init__.py +0 -0
- megadetector/api/synchronous/api_core/animal_detection_api/api_backend.py +152 -0
- megadetector/api/synchronous/api_core/animal_detection_api/api_frontend.py +263 -0
- megadetector/api/synchronous/api_core/animal_detection_api/config.py +35 -0
- megadetector/api/synchronous/api_core/tests/__init__.py +0 -0
- megadetector/api/synchronous/api_core/tests/load_test.py +110 -0
- megadetector/classification/__init__.py +0 -0
- megadetector/classification/aggregate_classifier_probs.py +108 -0
- megadetector/classification/analyze_failed_images.py +227 -0
- megadetector/classification/cache_batchapi_outputs.py +198 -0
- megadetector/classification/create_classification_dataset.py +627 -0
- megadetector/classification/crop_detections.py +516 -0
- megadetector/classification/csv_to_json.py +226 -0
- megadetector/classification/detect_and_crop.py +855 -0
- megadetector/classification/efficientnet/__init__.py +9 -0
- megadetector/classification/efficientnet/model.py +415 -0
- megadetector/classification/efficientnet/utils.py +607 -0
- megadetector/classification/evaluate_model.py +520 -0
- megadetector/classification/identify_mislabeled_candidates.py +152 -0
- megadetector/classification/json_to_azcopy_list.py +63 -0
- megadetector/classification/json_validator.py +699 -0
- megadetector/classification/map_classification_categories.py +276 -0
- megadetector/classification/merge_classification_detection_output.py +506 -0
- megadetector/classification/prepare_classification_script.py +194 -0
- megadetector/classification/prepare_classification_script_mc.py +228 -0
- megadetector/classification/run_classifier.py +287 -0
- megadetector/classification/save_mislabeled.py +110 -0
- megadetector/classification/train_classifier.py +827 -0
- megadetector/classification/train_classifier_tf.py +725 -0
- megadetector/classification/train_utils.py +323 -0
- megadetector/data_management/__init__.py +0 -0
- megadetector/data_management/annotations/__init__.py +0 -0
- megadetector/data_management/annotations/annotation_constants.py +34 -0
- megadetector/data_management/camtrap_dp_to_coco.py +237 -0
- megadetector/data_management/cct_json_utils.py +404 -0
- megadetector/data_management/cct_to_md.py +176 -0
- megadetector/data_management/cct_to_wi.py +289 -0
- megadetector/data_management/coco_to_labelme.py +283 -0
- megadetector/data_management/coco_to_yolo.py +662 -0
- megadetector/data_management/databases/__init__.py +0 -0
- megadetector/data_management/databases/add_width_and_height_to_db.py +33 -0
- megadetector/data_management/databases/combine_coco_camera_traps_files.py +206 -0
- megadetector/data_management/databases/integrity_check_json_db.py +493 -0
- megadetector/data_management/databases/subset_json_db.py +115 -0
- megadetector/data_management/generate_crops_from_cct.py +149 -0
- megadetector/data_management/get_image_sizes.py +189 -0
- megadetector/data_management/importers/add_nacti_sizes.py +52 -0
- megadetector/data_management/importers/add_timestamps_to_icct.py +79 -0
- megadetector/data_management/importers/animl_results_to_md_results.py +158 -0
- megadetector/data_management/importers/auckland_doc_test_to_json.py +373 -0
- megadetector/data_management/importers/auckland_doc_to_json.py +201 -0
- megadetector/data_management/importers/awc_to_json.py +191 -0
- megadetector/data_management/importers/bellevue_to_json.py +273 -0
- megadetector/data_management/importers/cacophony-thermal-importer.py +793 -0
- megadetector/data_management/importers/carrizo_shrubfree_2018.py +269 -0
- megadetector/data_management/importers/carrizo_trail_cam_2017.py +289 -0
- megadetector/data_management/importers/cct_field_adjustments.py +58 -0
- megadetector/data_management/importers/channel_islands_to_cct.py +913 -0
- megadetector/data_management/importers/eMammal/copy_and_unzip_emammal.py +180 -0
- megadetector/data_management/importers/eMammal/eMammal_helpers.py +249 -0
- megadetector/data_management/importers/eMammal/make_eMammal_json.py +223 -0
- megadetector/data_management/importers/ena24_to_json.py +276 -0
- megadetector/data_management/importers/filenames_to_json.py +386 -0
- megadetector/data_management/importers/helena_to_cct.py +283 -0
- megadetector/data_management/importers/idaho-camera-traps.py +1407 -0
- megadetector/data_management/importers/idfg_iwildcam_lila_prep.py +294 -0
- megadetector/data_management/importers/jb_csv_to_json.py +150 -0
- megadetector/data_management/importers/mcgill_to_json.py +250 -0
- megadetector/data_management/importers/missouri_to_json.py +490 -0
- megadetector/data_management/importers/nacti_fieldname_adjustments.py +79 -0
- megadetector/data_management/importers/noaa_seals_2019.py +181 -0
- megadetector/data_management/importers/pc_to_json.py +365 -0
- megadetector/data_management/importers/plot_wni_giraffes.py +123 -0
- megadetector/data_management/importers/prepare-noaa-fish-data-for-lila.py +359 -0
- megadetector/data_management/importers/prepare_zsl_imerit.py +131 -0
- megadetector/data_management/importers/rspb_to_json.py +356 -0
- megadetector/data_management/importers/save_the_elephants_survey_A.py +320 -0
- megadetector/data_management/importers/save_the_elephants_survey_B.py +329 -0
- megadetector/data_management/importers/snapshot_safari_importer.py +758 -0
- megadetector/data_management/importers/snapshot_safari_importer_reprise.py +665 -0
- megadetector/data_management/importers/snapshot_serengeti_lila.py +1067 -0
- megadetector/data_management/importers/snapshotserengeti/make_full_SS_json.py +150 -0
- megadetector/data_management/importers/snapshotserengeti/make_per_season_SS_json.py +153 -0
- megadetector/data_management/importers/sulross_get_exif.py +65 -0
- megadetector/data_management/importers/timelapse_csv_set_to_json.py +490 -0
- megadetector/data_management/importers/ubc_to_json.py +399 -0
- megadetector/data_management/importers/umn_to_json.py +507 -0
- megadetector/data_management/importers/wellington_to_json.py +263 -0
- megadetector/data_management/importers/wi_to_json.py +442 -0
- megadetector/data_management/importers/zamba_results_to_md_results.py +181 -0
- megadetector/data_management/labelme_to_coco.py +547 -0
- megadetector/data_management/labelme_to_yolo.py +272 -0
- megadetector/data_management/lila/__init__.py +0 -0
- megadetector/data_management/lila/add_locations_to_island_camera_traps.py +97 -0
- megadetector/data_management/lila/add_locations_to_nacti.py +147 -0
- megadetector/data_management/lila/create_lila_blank_set.py +558 -0
- megadetector/data_management/lila/create_lila_test_set.py +152 -0
- megadetector/data_management/lila/create_links_to_md_results_files.py +106 -0
- megadetector/data_management/lila/download_lila_subset.py +178 -0
- megadetector/data_management/lila/generate_lila_per_image_labels.py +516 -0
- megadetector/data_management/lila/get_lila_annotation_counts.py +170 -0
- megadetector/data_management/lila/get_lila_image_counts.py +112 -0
- megadetector/data_management/lila/lila_common.py +300 -0
- megadetector/data_management/lila/test_lila_metadata_urls.py +132 -0
- megadetector/data_management/ocr_tools.py +870 -0
- megadetector/data_management/read_exif.py +809 -0
- megadetector/data_management/remap_coco_categories.py +84 -0
- megadetector/data_management/remove_exif.py +66 -0
- megadetector/data_management/rename_images.py +187 -0
- megadetector/data_management/resize_coco_dataset.py +189 -0
- megadetector/data_management/wi_download_csv_to_coco.py +247 -0
- megadetector/data_management/yolo_output_to_md_output.py +446 -0
- megadetector/data_management/yolo_to_coco.py +676 -0
- megadetector/detection/__init__.py +0 -0
- megadetector/detection/detector_training/__init__.py +0 -0
- megadetector/detection/detector_training/model_main_tf2.py +114 -0
- megadetector/detection/process_video.py +846 -0
- megadetector/detection/pytorch_detector.py +355 -0
- megadetector/detection/run_detector.py +779 -0
- megadetector/detection/run_detector_batch.py +1219 -0
- megadetector/detection/run_inference_with_yolov5_val.py +1087 -0
- megadetector/detection/run_tiled_inference.py +934 -0
- megadetector/detection/tf_detector.py +192 -0
- megadetector/detection/video_utils.py +698 -0
- megadetector/postprocessing/__init__.py +0 -0
- megadetector/postprocessing/add_max_conf.py +64 -0
- megadetector/postprocessing/categorize_detections_by_size.py +165 -0
- megadetector/postprocessing/classification_postprocessing.py +716 -0
- megadetector/postprocessing/combine_api_outputs.py +249 -0
- megadetector/postprocessing/compare_batch_results.py +966 -0
- megadetector/postprocessing/convert_output_format.py +396 -0
- megadetector/postprocessing/load_api_results.py +195 -0
- megadetector/postprocessing/md_to_coco.py +310 -0
- megadetector/postprocessing/md_to_labelme.py +330 -0
- megadetector/postprocessing/merge_detections.py +412 -0
- megadetector/postprocessing/postprocess_batch_results.py +1908 -0
- megadetector/postprocessing/remap_detection_categories.py +170 -0
- megadetector/postprocessing/render_detection_confusion_matrix.py +660 -0
- megadetector/postprocessing/repeat_detection_elimination/find_repeat_detections.py +211 -0
- megadetector/postprocessing/repeat_detection_elimination/remove_repeat_detections.py +83 -0
- megadetector/postprocessing/repeat_detection_elimination/repeat_detections_core.py +1635 -0
- megadetector/postprocessing/separate_detections_into_folders.py +730 -0
- megadetector/postprocessing/subset_json_detector_output.py +700 -0
- megadetector/postprocessing/top_folders_to_bottom.py +223 -0
- megadetector/taxonomy_mapping/__init__.py +0 -0
- megadetector/taxonomy_mapping/map_lila_taxonomy_to_wi_taxonomy.py +491 -0
- megadetector/taxonomy_mapping/map_new_lila_datasets.py +150 -0
- megadetector/taxonomy_mapping/prepare_lila_taxonomy_release.py +142 -0
- megadetector/taxonomy_mapping/preview_lila_taxonomy.py +588 -0
- megadetector/taxonomy_mapping/retrieve_sample_image.py +71 -0
- megadetector/taxonomy_mapping/simple_image_download.py +219 -0
- megadetector/taxonomy_mapping/species_lookup.py +834 -0
- megadetector/taxonomy_mapping/taxonomy_csv_checker.py +159 -0
- megadetector/taxonomy_mapping/taxonomy_graph.py +346 -0
- megadetector/taxonomy_mapping/validate_lila_category_mappings.py +83 -0
- megadetector/utils/__init__.py +0 -0
- megadetector/utils/azure_utils.py +178 -0
- megadetector/utils/ct_utils.py +613 -0
- megadetector/utils/directory_listing.py +246 -0
- megadetector/utils/md_tests.py +1164 -0
- megadetector/utils/path_utils.py +1045 -0
- megadetector/utils/process_utils.py +160 -0
- megadetector/utils/sas_blob_utils.py +509 -0
- megadetector/utils/split_locations_into_train_val.py +228 -0
- megadetector/utils/string_utils.py +92 -0
- megadetector/utils/url_utils.py +323 -0
- megadetector/utils/write_html_image_list.py +225 -0
- megadetector/visualization/__init__.py +0 -0
- megadetector/visualization/plot_utils.py +293 -0
- megadetector/visualization/render_images_with_thumbnails.py +275 -0
- megadetector/visualization/visualization_utils.py +1536 -0
- megadetector/visualization/visualize_db.py +552 -0
- megadetector/visualization/visualize_detector_output.py +405 -0
- {megadetector-5.0.11.dist-info → megadetector-5.0.13.dist-info}/LICENSE +0 -0
- {megadetector-5.0.11.dist-info → megadetector-5.0.13.dist-info}/METADATA +2 -2
- megadetector-5.0.13.dist-info/RECORD +201 -0
- megadetector-5.0.13.dist-info/top_level.txt +1 -0
- megadetector-5.0.11.dist-info/RECORD +0 -5
- megadetector-5.0.11.dist-info/top_level.txt +0 -1
- {megadetector-5.0.11.dist-info → megadetector-5.0.13.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
directory_listing.py
|
|
4
|
+
|
|
5
|
+
Script for creating Apache-style HTML directory listings for a local directory
|
|
6
|
+
and all its subdirectories.
|
|
7
|
+
|
|
8
|
+
Also includes a preview of a jpg file (the first in an alphabetical list),
|
|
9
|
+
if present.
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
#%% Imports
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
import argparse
|
|
18
|
+
import re
|
|
19
|
+
|
|
20
|
+
import azure.common
|
|
21
|
+
from azure.storage.blob import BlobServiceClient, ContentSettings
|
|
22
|
+
|
|
23
|
+
from megadetector.utils.path_utils import is_image_file
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
#%% Directory enumeration functions
|
|
27
|
+
|
|
28
|
+
def create_plain_index(root, dirs, files, dirname=None):
|
|
29
|
+
"""
|
|
30
|
+
Creates the fairly plain HTML folder index including a preview of a single image file,
|
|
31
|
+
if any is present.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
root (str): path to the root directory, all paths in [dirs] and
|
|
35
|
+
[files] are relative to this root folder
|
|
36
|
+
dirs (list): list of strings, the directories in [root]
|
|
37
|
+
files (list): list of strings, the files in [root]
|
|
38
|
+
dirname (str, optional): name to print in the html,
|
|
39
|
+
which may be different than [root]
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
str: HTML source of the directory listing
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
if dirname is None:
|
|
46
|
+
dirname = root or '/'
|
|
47
|
+
|
|
48
|
+
html = "<!DOCTYPE html>\n"
|
|
49
|
+
html += "<html lang='en'><head>"
|
|
50
|
+
html += "<title>Index of {}</title>\n".format(dirname)
|
|
51
|
+
html += "<meta charset='UTF-8'>\n"
|
|
52
|
+
html += "<style>\n"
|
|
53
|
+
html += "body { font-family: Segoe UI, Helvetica, Arial, sans-serif; }\n"
|
|
54
|
+
html += "a { text-decoration:none; }\n"
|
|
55
|
+
html += "</style>\n"
|
|
56
|
+
html += "</head><body>\n"
|
|
57
|
+
|
|
58
|
+
html += "<h1>Index of {}</h1>\n".format(dirname)
|
|
59
|
+
|
|
60
|
+
# Insert preview image
|
|
61
|
+
jpg_files = [f for f in files if is_image_file(f)]
|
|
62
|
+
|
|
63
|
+
if len(jpg_files) > 0:
|
|
64
|
+
|
|
65
|
+
# This is slow, so defaulting to just the first image:
|
|
66
|
+
#
|
|
67
|
+
# Use the largest image file as this is most likely to contain
|
|
68
|
+
# useful content.
|
|
69
|
+
#
|
|
70
|
+
# jpg_file_sizes = [os.path.getsize(f) for f in jpg_files]
|
|
71
|
+
# largest_file_index = max(range(len(jpg_files)), key=lambda x: jpg_file_sizes[x])
|
|
72
|
+
|
|
73
|
+
html += "<a href='{0}'><img style='height:200px; float:right;' src='{0}' alt='Preview image'></a>\n".format(jpg_files[0])
|
|
74
|
+
else:
|
|
75
|
+
html += "\n"
|
|
76
|
+
# html += "<p style='width:15em; float:right; margin:0;'>[No preview available]</p>\n"
|
|
77
|
+
|
|
78
|
+
if root:
|
|
79
|
+
html += "<p><a href='../index.html'>To parent directory</a></p>\n"
|
|
80
|
+
else:
|
|
81
|
+
html += "\n"
|
|
82
|
+
# html += "<p>This is the root directory.</p>\n"
|
|
83
|
+
|
|
84
|
+
html += "<h2>Folders</h2>\n"
|
|
85
|
+
if len(dirs) > 0:
|
|
86
|
+
html += "<ul style='list-style-type: none; padding-left:1em;'>\n"
|
|
87
|
+
for dir in sorted(dirs):
|
|
88
|
+
html += "<li>📁 <a href='{0}/index.html'>{0}</a></li>\n".format(dir)
|
|
89
|
+
html += "</ul>\n"
|
|
90
|
+
else:
|
|
91
|
+
html += "<p style='padding-left:1em;'>No folders</p>\n"
|
|
92
|
+
|
|
93
|
+
html += "<h2>Files</h2>\n"
|
|
94
|
+
if len(files) > 0:
|
|
95
|
+
html += "<ul style='list-style-type: none; padding-left:1em;'>\n"
|
|
96
|
+
for fname in sorted(files):
|
|
97
|
+
if is_image_file(fname):
|
|
98
|
+
html += "<li>🖻 <a href='{0}'>{0}</a></li>\n".format(fname)
|
|
99
|
+
else:
|
|
100
|
+
html += "<li>🖺 <a href='{0}'>{0}</a></li>\n".format(fname)
|
|
101
|
+
html += "</ul>\n"
|
|
102
|
+
else:
|
|
103
|
+
html += "<p style = 'padding-left:1em;'>No files</p>\n"
|
|
104
|
+
|
|
105
|
+
# Add some space at the bottom because the browser's status bar might hide stuff
|
|
106
|
+
html += "<p style='margin:2em;'> </p>\n"
|
|
107
|
+
html += "</body></html>\n"
|
|
108
|
+
return html
|
|
109
|
+
|
|
110
|
+
# ...def create_plain_index(...)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def traverse_and_create_index(dir, sas_url=None, overwrite_files=False,
|
|
114
|
+
template_fun=create_plain_index, basepath=None):
|
|
115
|
+
"""
|
|
116
|
+
Recursively traverses the local directory [dir] and generates a index
|
|
117
|
+
file for each folder using [template_fun] to generate the HTML output.
|
|
118
|
+
Excludes hidden files.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
dir (str): directory to process
|
|
122
|
+
sas_url (str, optional): write-capable SAS URL that points to the same place as
|
|
123
|
+
[dir], used for the very esoteric scenario where [dir] is really a mounted
|
|
124
|
+
blob container, and we want to set the content-type on each file so the resulting
|
|
125
|
+
index can be viewed in a browser
|
|
126
|
+
overwrite_files (bool, optional): whether to over-write existing index file
|
|
127
|
+
template_fun (func, optional): function taking three arguments (string,
|
|
128
|
+
list of string, list of string) representing the current root, the list of folders,
|
|
129
|
+
and the list of files. Should return the HTML source of the index file.
|
|
130
|
+
basepath (str, optional): if not None, the name used for each subfolder in [dir]
|
|
131
|
+
in the output files will be relative to [basepath]
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
print('Traversing {}'.format(dir))
|
|
135
|
+
|
|
136
|
+
# Make sure we remove the trailing /
|
|
137
|
+
dir = os.path.normpath(dir)
|
|
138
|
+
|
|
139
|
+
# If we want to set the content type in blob storage using a SAS URL
|
|
140
|
+
if sas_url:
|
|
141
|
+
|
|
142
|
+
# Example: sas_url = 'https://accname.blob.core.windows.net/bname/path/to/folder?st=...&se=...&sp=...&...'
|
|
143
|
+
if '?' in sas_url:
|
|
144
|
+
# 'https://accname.blob.core.windows.net/bname/path/to/folder' and 'st=...&se=...&sp=...&...'
|
|
145
|
+
base_url, sas_token = sas_url.split('?', 1)
|
|
146
|
+
else:
|
|
147
|
+
# 'https://accname.blob.core.windows.net/bname/path/to/folder' and None
|
|
148
|
+
base_url, sas_token = sas_url, None
|
|
149
|
+
# Remove https:// from base url
|
|
150
|
+
# 'accname.blob.core.windows.net/bname/path/to/folder'
|
|
151
|
+
base_url = base_url.split("//", 1)[1]
|
|
152
|
+
# Everything up to the first dot is account name
|
|
153
|
+
# 'accname'
|
|
154
|
+
account_name = base_url.split(".", 1)[0]
|
|
155
|
+
# get everything after the first /
|
|
156
|
+
# 'bname/path/to/folder'
|
|
157
|
+
query_string = base_url.split("/", 1)[1]
|
|
158
|
+
# Get container name and subfolder
|
|
159
|
+
if '/' in query_string:
|
|
160
|
+
# 'bname', 'path/to/folder'
|
|
161
|
+
container_name, container_folder = query_string.split("/", 1)
|
|
162
|
+
else:
|
|
163
|
+
container_name, container_folder = query_string, ''
|
|
164
|
+
|
|
165
|
+
# Prepare the storage access
|
|
166
|
+
target_settings = ContentSettings(content_type='text/html')
|
|
167
|
+
blob_service = BlobServiceClient(
|
|
168
|
+
account_url=f'{account_name}.blob.core.windows.net',
|
|
169
|
+
credential=sas_token)
|
|
170
|
+
|
|
171
|
+
# Traverse directory and all sub directories, excluding hidden files
|
|
172
|
+
for root, dirs, files in os.walk(dir):
|
|
173
|
+
|
|
174
|
+
# Exclude files and folders that are hidden
|
|
175
|
+
files = [f for f in files if not f[0] == '.']
|
|
176
|
+
dirs[:] = [d for d in dirs if not d[0] == '.']
|
|
177
|
+
|
|
178
|
+
# Output is written to file *root*/index.html
|
|
179
|
+
output_file = os.path.join(root, "index.html")
|
|
180
|
+
|
|
181
|
+
if not overwrite_files and os.path.isfile(output_file):
|
|
182
|
+
print('Skipping {}, file exists'.format(output_file))
|
|
183
|
+
continue
|
|
184
|
+
|
|
185
|
+
print("Generating {}".format(output_file))
|
|
186
|
+
|
|
187
|
+
# Generate HTML with template function
|
|
188
|
+
dirname = None
|
|
189
|
+
if basepath is not None:
|
|
190
|
+
dirname = os.path.relpath(root,basepath)
|
|
191
|
+
html = template_fun(root[len(dir):], dirs, files, dirname)
|
|
192
|
+
|
|
193
|
+
# Write to file
|
|
194
|
+
with open(output_file, 'wt') as fi:
|
|
195
|
+
fi.write(html)
|
|
196
|
+
|
|
197
|
+
# Set content type in blob storage
|
|
198
|
+
if sas_url:
|
|
199
|
+
if container_folder:
|
|
200
|
+
output_blob_path = container_folder + '/' + output_file[len(dir) + 1:]
|
|
201
|
+
else:
|
|
202
|
+
output_blob_path = output_file[len(dir) + 1:]
|
|
203
|
+
try:
|
|
204
|
+
blob_client = blob_service.get_blob_client(container_name, output_blob_path)
|
|
205
|
+
blob_client.set_http_headers(content_settings=target_settings)
|
|
206
|
+
except azure.common.AzureMissingResourceHttpError:
|
|
207
|
+
print('ERROR: It seems the SAS URL is incorrect or does not allow setting properties.')
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
# ...def traverse_and_create_index(...)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
#%% Command-line driver
|
|
214
|
+
|
|
215
|
+
def main():
|
|
216
|
+
|
|
217
|
+
parser = argparse.ArgumentParser()
|
|
218
|
+
|
|
219
|
+
parser.add_argument("directory", type=str,
|
|
220
|
+
help='Path to directory which should be traversed.')
|
|
221
|
+
parser.add_argument("--basepath", type=str,
|
|
222
|
+
help='Folder names will be printed relative to basepath, if specified',
|
|
223
|
+
default=None)
|
|
224
|
+
parser.add_argument("--sas_url", type=str,
|
|
225
|
+
help='Blobfuse does not set the content-type property ' + \
|
|
226
|
+
'properly and hence index.html won\'t be accessible in the browser. If you want to set the ' + \
|
|
227
|
+
'content-type in the corresponding blob storage, provide the SAS URL that corresponds to the ' + \
|
|
228
|
+
'directory, e.g. if *directory* is /mountpoint/path/to/folder, then *--sas_url* looks like ' + \
|
|
229
|
+
'"https://accname.blob.core.windows.net/bname/path/to/folder?st=...&se=...&sp=...&..."')
|
|
230
|
+
parser.add_argument("--enable_overwrite", action='store_true', default=False,
|
|
231
|
+
help='If set, the script will overwrite existing index.html files.')
|
|
232
|
+
|
|
233
|
+
if len(sys.argv[1:]) == 0:
|
|
234
|
+
parser.print_help()
|
|
235
|
+
parser.exit()
|
|
236
|
+
|
|
237
|
+
args = parser.parse_args()
|
|
238
|
+
|
|
239
|
+
assert os.path.isdir(args.directory), "{} is not a valid directory".format(args.directory)
|
|
240
|
+
assert re.match('https?://[^\.]+\.blob\.core\.windows\.net/.+', args.sas_url), "--sas_url does not " + \
|
|
241
|
+
"match the format https://accname.blob.core.windows.net/bname/path/to/folder?..."
|
|
242
|
+
|
|
243
|
+
traverse_and_create_index(args.directory, overwrite_files=args.enable_overwrite, sas_url=args.sas_url, basepath=args.basepath)
|
|
244
|
+
|
|
245
|
+
if __name__ == '__main__':
|
|
246
|
+
main()
|