Initial commit

This commit is contained in:
Levent Duivel 2021-06-23 13:35:35 +05:00
commit 058e3fe762
7 changed files with 577 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/dist/
/build/

16
Pipfile Normal file
View File

@ -0,0 +1,16 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
parse = "*"
eyed3 = "*"
ffmpeg-python = "*"
pyinstaller = "*"
mutagen = "*"
[dev-packages]
[requires]
python_version = "3.9"

193
Pipfile.lock generated Normal file
View File

@ -0,0 +1,193 @@
{
"_meta": {
"hash": {
"sha256": "298dd79c62dc5270388c13321b35a57cc741bb43662b04fce47c0641ffac0f32"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.9"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"altgraph": {
"hashes": [
"sha256:1f05a47122542f97028caf78775a095fbe6a2699b5089de8477eb583167d69aa",
"sha256:c623e5f3408ca61d4016f23a681b9adb100802ca3e3da5e718915a9e4052cebe"
],
"version": "==0.17"
},
"coverage": {
"extras": [
"toml"
],
"hashes": [
"sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c",
"sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6",
"sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45",
"sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a",
"sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03",
"sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529",
"sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a",
"sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a",
"sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2",
"sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6",
"sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759",
"sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53",
"sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a",
"sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4",
"sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff",
"sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502",
"sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793",
"sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb",
"sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905",
"sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821",
"sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b",
"sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81",
"sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0",
"sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b",
"sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3",
"sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184",
"sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701",
"sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a",
"sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82",
"sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638",
"sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5",
"sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083",
"sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6",
"sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90",
"sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465",
"sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a",
"sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3",
"sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e",
"sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066",
"sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf",
"sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b",
"sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae",
"sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669",
"sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873",
"sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b",
"sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6",
"sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb",
"sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160",
"sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c",
"sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079",
"sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d",
"sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'",
"version": "==5.5"
},
"deprecation": {
"hashes": [
"sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff",
"sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"
],
"version": "==2.1.0"
},
"eyed3": {
"hashes": [
"sha256:4b5064ec0fb3999294cca0020d4a27ffe4f29149e8292fdf7b2de9b9cabb7518",
"sha256:97bd529384df1c3dbdd143d86bf1705729d97d862969a214696f9e32c32b5767"
],
"index": "pypi",
"version": "==0.9.6"
},
"ffmpeg-python": {
"hashes": [
"sha256:65225db34627c578ef0e11c8b1eb528bb35e024752f6f10b78c011f6f64c4127",
"sha256:ac441a0404e053f8b6a1113a77c0f452f1cfc62f6344a769475ffdc0f56c23c5"
],
"index": "pypi",
"version": "==0.2.0"
},
"filetype": {
"hashes": [
"sha256:353369948bb1c09b8b3ea3d78390b5586e9399bff9aab894a1dff954e31a66f6",
"sha256:da393ece8d98b47edf2dd5a85a2c8733e44b769e32c71af4cd96ed8d38d96aa7"
],
"version": "==1.0.7"
},
"future": {
"hashes": [
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.18.2"
},
"mutagen": {
"hashes": [
"sha256:6397602efb3c2d7baebd2166ed85731ae1c1d475abca22090b7141ff5034b3e1",
"sha256:9c9f243fcec7f410f138cb12c21c84c64fde4195481a30c9bfb05b5f003adfed"
],
"index": "pypi",
"version": "==1.45.1"
},
"packaging": {
"hashes": [
"sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5",
"sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==20.9"
},
"parse": {
"hashes": [
"sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"
],
"index": "pypi",
"version": "==1.19.0"
},
"pefile": {
"hashes": [
"sha256:a5d6e8305c6b210849b47a6174ddf9c452b2888340b8177874b862ba6c207645"
],
"markers": "sys_platform == 'win32'",
"version": "==2019.4.18"
},
"pyinstaller": {
"hashes": [
"sha256:f5c0eeb2aa663cce9a5404292c0195011fa500a6501c873a466b2e8cad3c950c"
],
"index": "pypi",
"version": "==4.2"
},
"pyinstaller-hooks-contrib": {
"hashes": [
"sha256:27558072021857d89524c42136feaa2ffe4f003f1bdf0278f9b24f6902c1759c",
"sha256:892310e6363655838485ee748bf1c5e5cade7963686d9af8650ee218a3e0b031"
],
"version": "==2021.1"
},
"pyparsing": {
"hashes": [
"sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1",
"sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"
],
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.4.7"
},
"pywin32-ctypes": {
"hashes": [
"sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942",
"sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"
],
"markers": "sys_platform == 'win32'",
"version": "==0.2.0"
},
"toml": {
"hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
"sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
"version": "==0.10.2"
}
},
"develop": {}
}

23
README.md Normal file
View File

@ -0,0 +1,23 @@
osu!pl
======
Export your osu! beatmaps as Music & Video Libraries and playlists
Requirements
------------
1. Install [ffmpeg](https://www.ffmpeg.org/) to PATH
2. For building, you gonna need pipenv: `pip install pipenv`
Install (Windows)
-----------------
Visit [releases](https://github.com/mostm/osu-pl/releases/latest), and grab latest one.
Build
-----
1. `git clone https://github.com/mostm/osu-pl.git`
2. `pipenv sync`
3. `pyinstaller main.spec`
Note: While project has been written to support multiplatform, osu!stable does not officially support multiplatform.
So there is no reason for me to test this under other platforms.
Submit your pull requests, if this becomes an issue for you.

94
legacy.py Normal file
View File

@ -0,0 +1,94 @@
import os
import shutil
import configparser
beatmap_dir = os.path.abspath(os.environ['LOCALAPPDATA']+'\\osu!\\Songs\\')
beatmaps = []
bm_osu = []
with os.scandir(os.path.abspath(beatmap_dir)) as it:
for entry in it:
if entry.is_dir():
try:
beatmap_id = int(str(entry.name).split(' ')[0])
except ValueError:
# I'm not sure what to do about unranked maps right now, we will exclude them
continue
beatmaps.append(entry.path)
beatmap_type = {
"id": 0, # You may parse for "[Metadata]\n\nBeatmapSetID:{sid}" (WARN: Earlier maps will lack this parameter (osu file format v3 < osu file format v14)) or use the one provided with path
"name": 'Author - Title', # I should get it from osu files rather than directory, but that's how it happens
"audio": ".\\somefile.mp3", # Parse for "[General]\n\nAudioFilename: {filename}" | DONE
"video": ".\\something.mp4" # Parse for "[Events]\n\nVideo,{timestamp},{filename}" (found mp4,avi,mpg) | plz check, TODO
}
for beatmap in beatmaps:
with os.scandir(os.path.abspath(beatmap)) as it:
bm = {
'id': int(str(os.path.split(beatmap)[1]).split(' ')[0]),
'name': str(os.path.split(beatmap)[1])[len(str(os.path.split(beatmap)[1]).split(' ')[0])+1:],
'audio': None,
'audio_length': None,
'video': None
}
print('{} {}'.format(bm['id'], bm['name']))
for entry in it:
if entry.is_file():
if entry.path.endswith('osu'):
# ConfigParser is actually overkill solution, although I set it up to work
# FixMe: This solution does not account for multiple (via diff) maps in one
# Although, ranked maps should never have this.
with open(entry.path, 'r', encoding="utf-8") as f:
config_string = '[global]\n' + f.read()
a = ''
for x in config_string.split('\n')[:config_string.split('\n').index('[Events]')-1]:
a += x+'\n'
config = configparser.ConfigParser(allow_no_value=True)
config.read_string(a)
# TODO: Rewrite to simple checks and add video checking.
bm['audio'] = os.path.abspath(os.path.dirname(entry.path)+'\\'+config.get('General', 'AudioFilename'))
elif entry.path.endswith('mp4') or entry.path.endswith('avi') or entry.path.endswith('mpg'):
bm['video'] = entry.path
bm_osu.append(bm)
text_playlist = ""
for bm in bm_osu:
if bm['audio']:
text_playlist += "#EXTINF:0,{0}\n{1}\n".format(bm['name'], bm['audio'])
text_playlist = text_playlist[:-1]
try:
with open('osu.m3u', 'w', encoding='utf-8') as file:
file.write(text_playlist)
except:
open('osu.m3u', 'x')
with open('osu.m3u', 'w', encoding='utf-8') as file:
file.write(text_playlist)
text_type = ""
for bm in bm_osu:
if bm['name']:
text_type += "{0}\n".format(bm['name'])
text_type = text_type[:-1]
try:
with open('osu.txt', 'w', encoding='utf-8') as file:
file.write(text_type)
except:
open('osu.txt', 'x')
with open('osu.txt', 'w', encoding='utf-8') as file:
file.write(text_type)
for bm in bm_osu:
if bm['audio']:
print('{} {}'.format(bm['id'], bm['name']))
if os.path.basename(bm['audio']).split('.')[-1] != '':
shutil.copy2(bm['audio'], "{}\\osu music\\{}.{}".format(os.getcwd(), bm['name'], os.path.basename(bm['audio']).split('.')[-1]))
if bm['video']:
shutil.copy2(bm['video'], "{}\\osu music\\{}.{}".format(os.getcwd(), bm['name'], os.path.basename(bm['video']).split('.')[-1]))
print('done, ty for use')

216
main.py Normal file
View File

@ -0,0 +1,216 @@
import os
import shutil
from pathlib import Path
import mutagen
from mutagen.easyid3 import EasyID3
from mutagen.id3 import ID3, APIC
import ffmpeg
import mimetypes
EasyID3.RegisterTextKey('comment', 'COMM')
def parse_beatmap(content):
section = None
section_content = None
pure_sections = ['events', 'timingpoints']
beatmap = {}
for line in content.split('\n'):
if line.startswith('//'):
continue
if line.startswith('['):
if section and section_content:
beatmap[section] = section_content
section = line[1:line.index(']')].lower()
section_content = dict()
if section in pure_sections:
section_content = list()
continue
if section in pure_sections:
section_content.append(line)
elif section and ':' in line:
key = line[:line.index(':')].lower()
value = line[line.index(':') + 1:].strip()
section_content[key] = value
return beatmap
def scan_beatmaps(root):
beatmap_sets = {}
for beatmap_path in Path(root).glob('**/*.osu'):
file = open(str(beatmap_path), 'r', encoding='utf-8').read()
beatmap = parse_beatmap(file)
beatmap_set = beatmap['metadata'].get('beatmapsetid')
if not beatmap['metadata'].get('beatmapsetid'):
p = beatmap_path.parent
beatmap_set = p.name.split(' ')[0]
if not beatmap_set.isdigit():
beatmap_set = 'Unranked'
bg = None
video = None
for event in beatmap['events']:
if event.startswith('0,0,'):
bg = event.split(',')[2].strip('"').strip()
if event.startswith('Video'):
video = [x.strip('"') for x in event.split(',')[1:]]
video = {'timing': video[0], 'filename': video[1]}
beatmap['background'] = bg
beatmap['video'] = video
beatmap['path'] = str(beatmap_path)
if not beatmap_sets.get(beatmap_set):
beatmap_sets[beatmap_set] = list()
beatmap_sets[beatmap_set].append(beatmap)
return beatmap_sets
def generalize_beatmap_sets(beatmap_sets):
# Generalize to only relevant data
generalized = {}
unique_warn = []
if beatmap_sets.get('Unranked'):
beatmap_sets.pop('Unranked')
for setid in beatmap_sets.keys():
set_data = {}
for map in beatmap_sets[setid]:
data = map['metadata']
data.pop('version')
if data.get('beatmapid'):
data.pop('beatmapid')
data.pop('beatmapsetid')
beatmap_dir = Path(map['path']).parent
data['audio'] = None
if map['general']['audiofilename']:
data['audio'] = str(beatmap_dir.joinpath(map['general']['audiofilename']).absolute())
data['video'] = map['video']
if data['video']:
data['video']['filename'] = str(beatmap_dir.joinpath(data['video']['filename']).absolute())
if not os.path.exists(data['video']['filename']):
if setid not in unique_warn:
print(f'Video for {setid} is mentioned, but doesn\'t exist!')
unique_warn.append(setid)
data['video'] = None
data['thumbnail'] = None
if map['background']:
data['thumbnail'] = str(beatmap_dir.joinpath(map['background']).absolute())
for k, v in data.items():
if not v:
continue
if not set_data.get(k) or all([k == 'thumbnail', v != '', v]):
set_data[k] = v
if set_data.get(k) != v:
if k == 'tags' and len(v) > len(set_data.get(k)):
set_data[k] = v
# print(f"{map['path']}: Conflict of data with set ({k}) | {set_data.get(k)} != {v}")
generalized[setid] = set_data
return generalized
def clean_and_allow_filename(dirty_filename, invalid='<>:"/\|?*'):
fn = str(dirty_filename)
for char in invalid:
fn = fn.replace(char, '')
return fn
def generate_library(beatmap_sets, music=True, video=False, music_target=None, video_target=None):
if music:
if not music_target:
music_target = f'{os.getcwd()}{os.path.sep}osu!MusicLibrary'
try:
os.mkdir(f"{music_target}")
except:
pass
for setid, beatmap in beatmap_sets.items():
try:
map = dict(beatmap)
dir_name = f"{map['title']} by {map['artist']} ({map['creator']})"
dir_name = clean_and_allow_filename(dir_name)
try:
os.mkdir(f"{music_target}{os.path.sep}{dir_name}")
except:
pass
if not map['audio'] or map['audio'] == 'virtual':
continue
ext = os.path.splitext(map['audio'])[1]
fn = f"{map['artist']} - {map['title']}{ext}"
fn = clean_and_allow_filename(fn)
file_target = f"{music_target}{os.path.sep}{dir_name}{os.path.sep}{fn}"
shutil.copy2(map['audio'], file_target)
map['audio'] = file_target
if map.get('thumbnail') and os.path.exists(map['thumbnail']):
ext = os.path.splitext(map['thumbnail'])[1]
file_target = f"{music_target}{os.path.sep}{dir_name}{os.path.sep}cover{ext}"
shutil.copy2(map['thumbnail'], file_target)
map['thumbnail'] = file_target
audiofile = mutagen.File(map['audio'], easy=True)
if audiofile:
audiofile['artist'] = map['artist']
audiofile['album'] = map['creator']
audiofile['albumartist'] = map.get('artistunicode') if map.get('artistunicode') else map['artist']
audiofile['title'] = map['title']
if map.get('tags'):
audiofile['comment'] = map['tags']
audiofile['tracknumber'] = ['1', '1']
audiofile.save()
if map.get('thumbnail') and not map['audio'].endswith('.ogg'):
audio = mutagen.File(map['audio'], easy=False)
if 'audio/vorbis' in audio.mime:
continue
with open(map.get('thumbnail'), 'rb') as albumart:
audio['APIC'] = APIC(
encoding=3,
mime=mimetypes.guess_type(map.get('thumbnail')),
type=3, desc='osu! Beatmap Thumbnail',
data=albumart.read()
)
audio.save()
except Exception as error:
print(f'[Music] Failure while processing {setid} | {type(error)} | {str(error)}')
if video:
if not video_target:
video_target = f'{os.getcwd()}{os.path.sep}osu!VideoLibrary'
try:
os.mkdir(f"{video_target}")
except:
pass
for setid, beatmap in beatmap_sets.items():
try:
if not beatmap.get('video') or beatmap.get('audio').endswith('virtual'):
continue
map = dict(beatmap)
fn = f"{map['artist']} - {map['title']} ({map['creator']}).mp4"
output_fp = f"{video_target}{os.path.sep}{clean_and_allow_filename(fn)}"
audio_in = ffmpeg.input(map['audio'])['a']
kw = {}
if map['video']['timing'] != '0':
kw['itsoffset'] = float(map['video']['timing']) / 1000
video_in = ffmpeg.input(map['video']['filename'], **kw)
streams = ffmpeg.probe(map['video']['filename'])['streams']
ow = False
for stream in streams:
if stream.get('codec_name') in ['h264', 'avc1', 'mpeg4']:
video_in = video_in[str(stream['index'])]
ow = True
if not ow:
for stream in streams:
if stream.get('codec_name') not in ['h264', 'avc1', 'mpeg4']:
output_fp = output_fp[:-len('mp4')] + 'mkv'
out = ffmpeg.output(audio_in, video_in, output_fp, vcodec='copy', acodec='copy', fflags='+genpts')
print(' '.join(out.compile()))
out.run(overwrite_output=True)
except Exception as error:
print(f'[Video] Failure while processing {setid} | {type(error)} | {str(error)}')
return
if __name__ == '__main__':
root = os.path.abspath(os.environ['LOCALAPPDATA'] + '\\osu!\\Songs\\')
print('Scanning Beatmaps')
beatmap_sets = scan_beatmaps(root)
print('Generalizing beatmap data')
beatmaps = generalize_beatmap_sets(beatmap_sets)
print('Generating Music & Video Libraries')
generate_library(beatmaps,
music=input('Music Library? (y/n) ').lower().startswith('y'),
video=input('Video Library? (y/n) ').lower().startswith('y'))
print('Done, thanks for usage!')

33
main.spec Normal file
View File

@ -0,0 +1,33 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['main.py'],
pathex=['C:\\Users\\Levent\\Stuff\\Projects\\osu!pl'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True )