Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add file listing required packages and fix access to fields in recordclass #15

Open
wants to merge 1,340 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
1340 commits
Select commit Hold shift + click to select a range
9b475a4
Completed shortest path operation for weighted graphs
Aug 4, 2021
1f844bb
Add Turala example as a command line option
Aug 4, 2021
cc21f99
Bug fixes plus Turala MST and Shortest Path example graphs
Aug 4, 2021
0e27d01
Merge pull request #250 from JMCanning78/Issue249-add-Dijkstras-short…
JMCanning78 Aug 4, 2021
2b31204
Renaming SimpleQueue.py to Queue.py
Aug 5, 2021
ffcca6c
Fix variable name typos
Aug 5, 2021
ab8b407
Check for empty directory name before searching for files
Aug 6, 2021
2c5481d
Make AlgorithmVisualizations search for PythonVisualizations folder
Aug 6, 2021
a3ada59
Avoid infinite loops in resizing the codeText window
Aug 6, 2021
dbe6a1d
Set timer to avoid too many codeText resize events
Aug 6, 2021
332eba7
Show timeout ID in debug messages
Aug 6, 2021
8119662
Set timer to prevent infinite loop of codeText resizing.
Aug 6, 2021
e4fb616
Shorten timeout period on resizing for more responsiveness
Aug 6, 2021
8fc64ec
Select all text in entries on FocusIn and restrict edge weight range
Aug 6, 2021
172d555
Merge pull request #254 from JMCanning78/Issue252-edge-weight-text-en…
JMCanning78 Aug 6, 2021
e9ab6d9
Merge pull request #251 from JMCanning78/Issue177-rename-SimpleQueue-…
NataniaBirnbaum Aug 6, 2021
8310ff4
Show infinite cost with infinity symbol (except in trinket)
Aug 9, 2021
40e4d8c
Merge pull request #255 from JMCanning78/Show-infinity-symbol
JMCanning78 Aug 9, 2021
f8598b9
Clear hint on Unmap event and use transient in some situations
Aug 19, 2021
94048ab
Merge pull request #256 from JMCanning78/issue226-tooltips
JMCanning78 Aug 19, 2021
76e5e75
Ensure all items added to costs table are marked as temporary variables
Aug 19, 2021
25c9aeb
Add a generic event handler for debugging
Aug 20, 2021
eb352eb
Add debugging option to command line
Aug 20, 2021
88adc83
Prevent transient on Tk object and Enable detailed event logs
Aug 20, 2021
693a077
Re-display adjacency matrix on repositioning under Windows
JMCanning Aug 20, 2021
1d63430
Set adj mat as transient once it is visible
JMCanning Aug 21, 2021
977316d
Move command line parsing to base and force button states after
Aug 21, 2021
cb451e0
Merge pull request #258 from JMCanning78/Issue257-adjmatrix-in-Windows
JMCanning78 Aug 21, 2021
9ef90f5
Use lower case for argument hints
Aug 25, 2021
105b449
Merge pull request #259 from JMCanning78/Issue157-hints
JMCanning78 Aug 25, 2021
3ad8ff9
Zooming out can be done with other mouse buttons as well as shift key
Aug 25, 2021
6e29718
Rotate left can be done with other mouse buttons as well as shift key
Aug 25, 2021
aec1438
Merge pull request #260 from JMCanning78/Issue253-other-mouse-buttons
JMCanning78 Aug 25, 2021
21886be
Add command line arguments to randomly fill heap
Aug 25, 2021
7f03c11
Adjust shift delta for copied nodes
Aug 26, 2021
27dcd66
Convert Heap to use Table and adjust layout to reduce overlaps
Aug 28, 2021
29187b5
Merge pull request #261 from JMCanning78/Issue224-fix-heapify-overlap
JMCanning78 Aug 30, 2021
f8fe9dc
Fix list argument initialization in Tables
Aug 30, 2021
391edfd
Add command line options to fill tree
Aug 30, 2021
93b99bf
Fix fading of local variables in recursive traverse calls
Aug 30, 2021
9c7d5bc
Merge pull request #262 from JMCanning78/Issue222-fade-local-Tree234-…
JMCanning78 Aug 30, 2021
5d59a59
Set up resize handler for runAllVisualizationMenu.
Aug 31, 2021
aa51bc5
Remove check for resizing change to make it work on Windows
Aug 31, 2021
ffb9c7f
Reposition adjacency matrix after new graph operation
Aug 31, 2021
1b5a597
Remove deprecated drawable.py (in favor of drawnValue.py)
Aug 31, 2021
425b8a6
Dismiss menubutton even in Trinket to see speed slider
Sep 1, 2021
5c46ba6
Add way to expose version info in Trinket
Sep 1, 2021
2430ea9
Use commit hash as version
Sep 1, 2021
d7ebeb3
Update chapters for hash tables and quadtrees
Sep 1, 2021
f492a95
Center revised introduction text within window and fix background color
Sep 2, 2021
d42f49f
Use same bg color for intro frame and labels
Sep 2, 2021
9bf9553
Use same bg color for top level window
JMCanning Sep 2, 2021
c599c17
Remove disclaimer about resizing not working
Sep 2, 2021
d867cd3
Revise instructions for use of both runAll programs
Sep 2, 2021
b020fb4
Revise generic event handler to take sequence of fields
Sep 3, 2021
1802b9a
Remove unused handler
Sep 3, 2021
07cea67
Center introduction text within tab on every exposure
Sep 3, 2021
b7f904c
Merge pull request #263 from JMCanning78/Issue225-runAllVizMenu-resizing
JMCanning78 Sep 3, 2021
736a2b6
Change wording about Stern College for Women
JMCanning78 Sep 3, 2021
040d0ff
Use older subprocess API for broader compatiblity
JMCanning78 Sep 4, 2021
3730ff5
Tweak canvas width when scrollbars are present
Sep 7, 2021
305c663
Merge pull request #265 from JMCanning78/Issue240-fix-disappearing-sc…
JMCanning78 Sep 7, 2021
791a9ac
Fix scrollToSee's canvas size estimate & bounding box selection algor…
Sep 11, 2021
f635602
Scroll to see vMap index when set
Sep 11, 2021
18dfd98
Reposition traverse type display to allow better scrolling
Sep 11, 2021
9d4531a
Merge pull request #266 from JMCanning78/Issue207-fix-scrolltosee-on-…
JMCanning78 Sep 11, 2021
c4984df
Merge branch 'master' into issue81--createBasicQuadTreePointVisualiza…
Sep 13, 2021
e93b5da
Fix bad parentheses in setArguments
Sep 13, 2021
812df8d
Remove historical version of QuadTree.py
Sep 13, 2021
1ef6346
Clean up imports and add hints for operations and their arguments
Sep 13, 2021
985db08
Limit points to a region of the canvas
Sep 14, 2021
00fadd2
Enforce use of Animation enum in startAnimations + cosmetic changes
Sep 14, 2021
6536222
Always cleanup before returning from _insert and validate arg length
Sep 14, 2021
759995b
Double-click searches to find unique label and labels start at P0
Sep 14, 2021
da2461c
Refactor using drawnValue, user vs canvas coords, and hiding lines
Sep 15, 2021
d697ad9
Merge pull request #136 from JMCanning78/issue81--createBasicQuadTree…
JMCanning78 Sep 15, 2021
69d98c6
Keey root highlight visible
Sep 15, 2021
8c33891
Allow highlightCode to return a value to be used in Boolean expressions
Sep 21, 2021
43babbc
Show code and animation for Insert and Find Exact operations
Sep 21, 2021
7266d64
Merge pull request #268 from JMCanning78/Issue82-animate-quadtree-ins…
JMCanning78 Sep 21, 2021
c5ca101
Add hashed_rectangle (polygon) item to Scrim
Oct 4, 2021
24b1a5d
Add Find Nearest and Random Fill to QuadTree
Oct 5, 2021
d169110
Use tuples to guarantee key order when enumerating quadrants
Oct 5, 2021
b5b4560
Update app name in runAllVisualizations* for point quadtree
Oct 6, 2021
770775e
Update ans and diff in findnearest based on result from _nearest
Oct 7, 2021
ee24aa6
Add utility for copying canvas item event handlers
Oct 7, 2021
165f4ab
Pass on point region rectangle handlers to bounds and other covering …
Oct 7, 2021
f153b30
Eliminate scrollbars around point region on canvas
Oct 7, 2021
7c89db7
Allow boundary display to be toggled anytime
Oct 7, 2021
65c3f3d
Rename main to DatastructureVisualizations.py
Oct 8, 2021
d62a19a
Remove unneeded __init__.py
Oct 8, 2021
00530b4
Update README wording
Oct 8, 2021
bbaac64
Remove link to running repo on repl.it since it is flaky
Oct 8, 2021
f82a5de
Rename datastructure visualizations and minimize imports
Oct 8, 2021
760e60c
Add utility to export all datastructure visualizations as a macOS exe…
Oct 11, 2021
1f0fc16
Fix comment
Oct 11, 2021
82d0c17
Enhance options for export_macOS
Oct 11, 2021
0794046
Make export_macOS.py executable
Oct 15, 2021
2c845c7
Add option to show major.minor version number on intro
Oct 19, 2021
960d378
Add options for version management and code signing
Oct 19, 2021
5b6ab10
Add numeric precedence labels to the operator precedence table
Oct 28, 2021
1727a9f
Use OutputBox for output
Oct 28, 2021
75d5e03
Shorten floating point values and erase final result rectangle
Oct 28, 2021
7aeeaa0
Fix positioning of text appended to output box. Add testing options.
Oct 28, 2021
3b93c8a
Fix typo in comment
Oct 28, 2021
5a47235
Center result in output text box
Oct 28, 2021
9425b42
Merge pull request #270 from JMCanning78/Issue269-numeric-precedence-…
JMCanning78 Oct 28, 2021
a31c1e3
Enable show inserted button at all times
Oct 28, 2021
cee9de6
Fix comment typo
Oct 30, 2021
aa033a0
Use OutputBox for output of First, Delete First, Search, and Traverse…
Oct 30, 2021
8dc0b4f
Return data of first item or item matching key in all delete operations.
Nov 1, 2021
57bf79c
Make delete animations consistent in both orddered and linked lists
Nov 2, 2021
d19a1a8
Merge pull request #272 from JMCanning78/Issue271-OutputBox-in-linked…
JMCanning78 Nov 2, 2021
02acf2d
Capitalize fill in Random Fill label
Nov 17, 2021
c964186
Scroll to see tree object by default
Nov 20, 2021
d617fd2
Place 2-3-4 tree lower to expose tree object at launch
Nov 20, 2021
a8c6db8
Revise search code to match change in textbook
Nov 24, 2021
2c0cec3
Shorten exception text for deleting missing key in hash table
Dec 9, 2021
72e9eee
Fix typo in variable name
Dec 9, 2021
f44b494
Fix bug with flattening list of canvas items
Dec 16, 2021
97088b4
Fixed findNearest(), added Traverse stub, and show insert vs update
Jan 20, 2022
b239cb8
Remove extraneous whitespace from arguments
Jan 25, 2022
7efd34a
Center output box under tree root center
Jan 26, 2022
7a3b817
Fix item deletion in promote_successor and use OutputBox for result
Jan 28, 2022
7c0a90f
Use OutputBox for traverse output.
Jan 28, 2022
e898c48
Enhance appendText to accept lists of text items to append
Jan 28, 2022
6172ca2
Use OutputBox for removeMax, peek, and traverse operations
Jan 28, 2022
00510d4
Use BBoxCenter utility
Jan 28, 2022
131c026
Remove unneeded import
Jan 28, 2022
0ba03a1
Change to use OutputBox for deleted result
Jan 28, 2022
9e9911a
Use OutputBox for traverse output and leave more space for index labels
Jan 29, 2022
2e4c30d
Merge pull request #279 from JMCanning78/Issue276-align-output-box
JMCanning78 Jan 29, 2022
756d67b
Check for canvas size keyword arguments in constructor
Feb 3, 2022
e5646d0
Add position control for table label
Feb 3, 2022
1bd46bb
Change tree traversal to use stack instead of recursion
Feb 3, 2022
0a0ef22
Handle traverse of empty tree
Feb 3, 2022
55800c0
Place table label automatically if not specified.
Feb 3, 2022
4144814
Support setting of canvas item cooridnates
Feb 3, 2022
d1c28c3
Make stack larger and easier to read
Feb 3, 2022
e186980
Add command line option for -N to randomly fill with N items
Feb 3, 2022
77161ca
Center stack within stackWidth column
Feb 3, 2022
a37cf23
Merge pull request #280 from JMCanning78/Issue277-binary-tree-stack-t…
JMCanning78 Feb 4, 2022
8491c74
Make wait a keyword parameter
Feb 4, 2022
0401891
Use python repr to add quotes on string value
Feb 4, 2022
9ebe7ad
Use set intersect to update callEnviron
Feb 5, 2022
63c15f5
Simplify calculation of width of output box
Feb 5, 2022
9a0d36d
Add code highlight on traverse yield statement
Feb 5, 2022
f96eb0a
Implement stack-based non-recursive traverse in Tree234
Feb 5, 2022
e3183fe
Constrain output box right edge from overlapping traverse stack
Feb 7, 2022
0b0cad9
Enable scaling in Table displays
Feb 7, 2022
26eecd8
Predicate for app animations paused or waiting for code step
Feb 9, 2022
308817d
Get default scale from app attribute
Feb 9, 2022
93aa8ff
Fix output box font setting and add command line testing
Feb 9, 2022
e0a42fd
Scale text items at creation
Feb 9, 2022
063f9f6
Correct text items and output box font; prevent zoom change during an…
Feb 9, 2022
9549e68
Merge pull request #281 from JMCanning78/Issue278-Tree234-stack-based…
JMCanning78 Feb 9, 2022
5268906
Get default scale from app using table
Feb 24, 2022
1dc092e
Add bbox approximation for hidden items
Mar 1, 2022
3b87654
Fix positioning of traverse stack and variables when zoom changes
Mar 1, 2022
1a7e47a
Enforce binary weights forunweighted graphs created from command line
Mar 1, 2022
95ab100
Allow random fill of hash table from command line
Mar 1, 2022
da03707
Remove separator characters from randomly generated strings
Mar 1, 2022
488bbf4
Merge pull request #283 from JMCanning78/Issue282-fix-Tree234-traverse
JMCanning78 Mar 1, 2022
109d845
Remove unused iteratorStack variable
Mar 2, 2022
df6089d
Fix typo in comment
Mar 2, 2022
b493e4d
Implement traverse example print loop (without iterator)
Mar 2, 2022
5d00462
Implement traverse iterator with stack
Mar 3, 2022
08a78d4
Restore local variables after loop exit
Mar 6, 2022
831c46d
Merge pull request #284 from JMCanning78/Issue275-add-traverse-to-qua…
JMCanning78 Mar 6, 2022
4cb9429
Move trinket export into .export directory
Mar 10, 2022
48abb42
Correct name of trinket export module
Mar 10, 2022
fd4fa5c
Correct name of trinket export module again
Mar 10, 2022
a20300c
Use git module for commit attributes and make callable
Mar 11, 2022
74aa306
Adding GitPython as a requirement
Mar 11, 2022
fff5433
Hide binary tree base class from runAllVisualization search
Mar 12, 2022
d39d4e0
Make export_macOS callable by other modules
Mar 12, 2022
41506ae
Use make_release to update version and export platform bundles
Mar 12, 2022
5fe4146
Enhance make_release with target platforms
Mar 14, 2022
296d158
Release 1.0
Mar 15, 2022
77118c6
Delete and recreate existing tag when --force is selected
Mar 15, 2022
740183e
Release 1.0
Mar 15, 2022
06b566b
Reset version numbers
Mar 15, 2022
dfe5880
Release 1.0
Mar 15, 2022
b4d2625
Release 2.0
Mar 15, 2022
58035e6
Reset version number
Mar 15, 2022
0cdb5a9
Release 1.0
Mar 15, 2022
5483724
Reset version number
Mar 15, 2022
507e05b
Release 1.0
Mar 15, 2022
0299be8
Reset version number
Mar 15, 2022
e4b4c1a
Release 1.0
Mar 15, 2022
98a03b6
Reset version number
Mar 15, 2022
74aabfc
Release 1.0
Mar 15, 2022
f23d060
Reset version number
Mar 15, 2022
dacfce4
Release 1.0
Mar 15, 2022
f87f82c
Reset version number
Mar 15, 2022
6d91815
Release 1.0
Mar 15, 2022
281fc77
Reset version number
Mar 15, 2022
bc56cb9
Get HEAD branch by default for commit/relase info
Mar 15, 2022
0a15d42
Move spec file into release directory
Mar 15, 2022
fd976ba
Backup entire release directory and check release tag
Mar 15, 2022
a034832
Utility for getting function keyword parameters
Mar 15, 2022
8a39e6b
Release 1.0
Mar 16, 2022
bb7b047
Default to no codesigning and show more disk image messages
Mar 16, 2022
0f24fdc
Add message for completed release directory
Mar 16, 2022
8c9a8f7
Refactor common export code, add source dir, and create windows export
Mar 18, 2022
69ad83b
Add PyInstaller to requirements for exporting
Mar 20, 2022
2f628f1
Add universal C run-time libraries to data files
Mar 20, 2022
a624520
Remove default sign identity
Mar 20, 2022
fef51ba
export_windows correctly builds a single file executable but does not…
Apr 4, 2022
db08323
Catch subprocess errors and report error strings
Apr 5, 2022
2022e38
Add code signing of executable
Apr 5, 2022
7ceaa5a
Report subprocess output more clearly
Apr 5, 2022
0caa0b4
Add password option for signer certificate
Apr 19, 2022
e65ca2f
Refactor hidden command line argument code to common
Apr 19, 2022
02ea913
Improve code signing and packaging of macOS executable
Apr 19, 2022
d73401e
Merge pull request #287 from JMCanning78/Issue264-executables-for-win…
JMCanning78 Apr 19, 2022
1ecb541
Allow zoom changes when animation is stopped
Apr 19, 2022
619c705
Merge pull request #288 from JMCanning78/Issue286-fix-double-click-zoom
JMCanning78 Apr 19, 2022
66b9737
Use Apple Distribution signing identity by default
May 24, 2022
ab44e95
Capitalize words in button labels of RedBlackTree
May 27, 2022
80b2bfe
Capitalize words in button labels of hash tree visualizations
May 28, 2022
c1032a7
Unify command line argument processing for hash table visualizations
May 30, 2022
f047228
Add command line option to initialize random seed for Heap
Jun 1, 2022
cdce26e
Shift double-click on graph backrgound deselects all selected vertices
Jun 3, 2022
c8f1400
Fix bug in assignFromTemp when narrow array cells have no text for key
Jun 6, 2022
8ea69d2
Merge pull request #297 from JMCanning78/Issue296-quicksort-failure
JMCanning78 Jun 6, 2022
edcf633
Redo animation of updateHeight using new textbook code
Jun 10, 2022
3cfa82c
Merge pull request #299 from JMCanning78/Issue289-AVLTree-updateHeight
JMCanning78 Jun 10, 2022
c3e37f8
Cut off nodes moved beyond depth limit in binary trees
Jun 10, 2022
93c6999
Update AVLTree to handle any nodes cut off moving subtrees
Jun 10, 2022
60b9e1f
Merge pull request #300 from JMCanning78/Issue291-nodes-beyond-level-4
JMCanning78 Jun 10, 2022
d6093bd
Fix overlap of search output box with long hashed values
Jun 13, 2022
51ec62b
Merge pull request #301 from JMCanning78/Issue292-hashed-value-overlap
JMCanning78 Jun 13, 2022
527f3e2
Add utility to categorize command line arguments
Jun 14, 2022
2174cbe
Unify command line argument processing for numeric args and options
Jun 14, 2022
486066a
Merge pull request #303 from JMCanning78/Issue290-numeric-args-traili…
JMCanning78 Jun 15, 2022
2c48b38
Fixed highlghted edges overlapping vertices
Jun 15, 2022
82e2861
Avoid hang in runAllVisualizations notebook
Jun 15, 2022
e73ff8a
Use enableButtons to determine correct button state after arg change
Jun 15, 2022
893a71e
Merge pull request #304 from JMCanning78/Issue295-edges-obscure-vertices
JMCanning78 Jun 15, 2022
5ec04d5
Improve printout of PyInstaller options
Jun 16, 2022
2a9018e
Codesign images and specify macOS target architecture
Jun 16, 2022
34455aa
Use dispose routine to clean up items in SortingBase
Jun 26, 2022
f68b396
Ensure old items replaced by shifts during insertion are erased
Jun 26, 2022
cf619eb
Merge pull request #308 from JMCanning78/Issue307-fix-priority-queue-…
JMCanning78 Jun 26, 2022
3a5f69d
Allow callable return values in highlightCode to delay evaluation
Jun 27, 2022
20d93af
Fix bug in assignElement when narrow array cells have no text for key
Jun 28, 2022
5a8500c
Crosslink to datastructures.live
Aug 23, 2022
17aa9e4
Add file encoding to aid reading files on Windows
Jul 18, 2023
00df2b7
Add double-click handler to clear code for screenshots
Jul 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
138 changes: 138 additions & 0 deletions .export/export_common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#! /usr/bin/env python3
__doc__ = '''
Utilties common to macOS and Windows exports
Run this in the directory where the visualization apps and associated PNG
files are stored.
'''

import sys, glob, os, shutil, json

class Hidden(object):
def __init__(self, thing):
self.thing = thing

def __str__(self):
return '*HIDDEN*'

def commandLineArg(thing):
'Get the string representation for printing a command line argument'
return ('{!r}'.format(thing) if isinstance(thing, str) and ' ' in thing
else str(thing))

def makeCommand(args):
'Replace any hidden items with the actual value in command line arguments'
return [item.thing if isinstance(item, Hidden) else item for item in args]

if not hasattr(sys, 'path'): sys.path = []
for dir in ('.', '../PythonVisualizations'):
if dir not in sys.path:
sys.path.append(dir)

try:
from allVisualizationsCommon import *
except ModuleNotFoundError:
from .allVisualizationsCommon import *

def getVersion(version_file, verbose=0):
if os.path.exists(version_file):
with open(version_file, 'r') as vFile:
version = json.load(vFile)
else:
version = [1, 0]
if verbose > 0:
print('Version read from {}'.format(version_file)
if os.path.exists(version_file) else 'Version',
'is {}.{}'.format(*version))
return version

def buildApplication(
appName: 'File name of application to export',
version: 'Version in the form of a string or list of numbers',
source_directory: 'Path to source file directory' = '.',
verbose: 'Verbosity level of progress messages' =0):

if not hasattr(sys, 'path'): sys.path = []
if source_directory not in sys.path:
sys.path.append(source_directory)

pyfiles = set(glob.glob(os.path.join(source_directory, '*.py')))
toRemove = set()
exportPyFiles = set(f for f in pyfiles if os.path.basename(f) not in
('runAllVisualizations.py', 'runAllVisualizationsMenu.py'))
pngfiles = set(glob.glob(os.path.join(source_directory, '*.png')))

visualizations = findVisualizations(pyfiles, max(0, verbose - 1))

if any(len(s) == 0 for s in (visualizations, pngfiles)):
print('Source directory = {!r}'.format(source_directory))
for files, kind in (
(visualizations, 'Visualizations'),
(pngfiles, 'PNG')):
print('Could not find any {} files.'.format(kind) if len(files) == 0
else 'Found {} {} file{}'.format(
len(files), kind, '' if len(files) == 1 else 's'))
print('Is the source directory where the visualization files are?')
raise Exception('Missing files for export')

if verbose > 0:
print('Found {} python file{} and {} visualization app{}'.format(
len(pyfiles), '' if len(pyfiles) == 1 else 's',
len(visualizations), '' if len(visualizations) == 1 else 's'))
if verbose > 1:
for pyfile in pyfiles:
vizClasses = [
viz.__name__ for viz in visualizations
if (viz.__module__ + '.py') == os.path.basename(pyfile)]
print(pyfile, '->' if vizClasses else '', ', '.join(vizClasses))

appFilename = appName
model = os.path.join(source_directory, 'runAllVisualizationsMenu.py')
with open(appFilename, 'w') as appFile:
with open(model, 'r') as modelFile:
for line in modelFile:
if line.startswith("if __name__ == '__main__':"):
print('import {}'.format(', '.join(
viz.__module__ for viz in visualizations)), file=appFile)
print('showVisualizations(({}), version={})'.format(', '.join(
'{}.{}'.format(viz.__module__, viz.__name__)
for viz in visualizations), version), file=appFile)
break
print(line, file=appFile, end='')
if verbose > 0:
print('Created application file with {} visualiazation{} in {}'.format(
len(visualizations), '' if len(visualizations) == 1 else 's',
appFilename))
return appFilename

def backupFiles(
filesToBackup: 'Files or directories to backup',
backup_extension: 'File extension for backed up copy' = '.bak',
verbose: 'Verbosity level of progress messages' =0):

for item in filesToBackup:
if os.path.exists(item):
backup_item = item + backup_extension
if os.path.exists(backup_item):
if verbose > 0:
print('Removing', backup_item, '...')
if os.path.isdir(backup_item):
shutil.rmtree(backup_item)
else:
os.remove(backup_item)
if verbose > 0:
print('Renaming', item, 'to', backup_item)
os.rename(item, backup_item)

def printPyInstallerArguments(data_args, PyInstallerArgs, prefix=' '):
print('PyInstaller arguments:')
for arg in data_args:
print(prefix, arg, end='' if arg.startswith('-') else '\n')
for i, arg in enumerate(PyInstallerArgs):
option = arg.startswith('--')
end = i >= len(PyInstallerArgs) - 1
if option:
print(
prefix, arg,
end='\n' if end or PyInstallerArgs[i + 1].startswith('--') else ' ')
else:
print(repr(arg))
182 changes: 182 additions & 0 deletions .export/export_macOS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#! /usr/bin/env python3
__doc__ = '''
Export a self-contained macOS executable of all datastructure visualizations.
Run this in the directory where the visualization apps and associated PNG
files are stored.
'''

import PyInstaller.__main__
import sys, glob, os, argparse, subprocess, tempfile, shutil
from subprocess import CompletedProcess

if not hasattr(sys, 'path'): sys.path = []
for dir in ('.', '../PythonVisualizations'):
if dir not in sys.path:
sys.path.append(dir)

from export_common import *

def export_macOS(
appName: 'Base name of application to export'
='DatastructureVisualizations',
version_file: 'JSON file containing the version tuple' = 'version.json',
source_directory: 'Directory containing source and PNG files' = '.',
icon: 'Path to icon file' ='design/Datastructure-Visualizations-icon.icns',
ID: 'Bundle ID for macOS' ='com.shakumant.dev.{name}',
disk_image: 'Disk image (dmg) name' ='{name}{version}.dmg',
sign_identity: 'Common name of codesign cert' ='Apple Distribution',
keep: 'Keep executable source code file created for export.' =False,
backup: 'File extension for backups of last export' ='.bak',
work_dir: 'Directory for work files, .log, .pyz and etc.' ='./build',
distribution: 'Name of export distribution directory' ='./dist',
verbose: 'Verbosity level of progress messages' =0):

if verbose > 0:
print('Verbosity level:', verbose)
version = getVersion(version_file, verbose)
appFilename = buildApplication(
appName + '.py', version, source_directory=source_directory,
verbose=verbose)

iconfiles = set(glob.glob(icon))
iconFilename = os.path.abspath(icon)
dmgFilename = disk_image.format(name=appName,
version='_{:02d}_{:02d}'.format(*version))

images = os.path.join(os.path.abspath(source_directory), '*.png')
data_args = ['--add-data', images + ':.']

specPath = os.path.dirname(distribution)
backupFiles((work_dir, distribution, appName,
os.path.join(specPath, appName) + '.spec', dmgFilename),
backup_extension=backup, verbose=verbose)

if sign_identity:
if verbose > 0 and glob.glob(images):
print('Codesigning images')
for imageFile in glob.glob(images):
imagesign_cmd = ['codesign', '-s', sign_identity, imageFile]
if verbose > 1:
print('Running:', ' '.join(imagesign_cmd), ' ...')
result = subprocess.run(imagesign_cmd, capture_output=True)
if result.returncode == 1 and result.stderr.decode().strip().endswith(
'is already signed'):
if verbose > 1:
print('Ignoring reminder that file is already codesigned')
elif result.returncode != 0:
print('Error code from codesign =', result.returncode)
for msg in (result.stdout, '-' * 77, result.stderr):
text = (msg if isinstance(msg, str) else msg.decode()).strip()
if text:
print(text)

logLevel = ['ERROR', 'WARN', 'INFO', 'DEBUG'][max(0, min(4, verbose))]
PyInstallerArgs = [
'--name', appName, '--distpath', distribution, '--workpath', work_dir,
'--specpath', specPath, '--windowed', '--icon', iconFilename,
'--log-level', logLevel, '--target-arch', 'x86_64',
'--osx-bundle-identifier', ID.format(name=appName) ]
if sign_identity:
PyInstallerArgs.extend(['--codesign-identity', sign_identity])

if verbose > 1:
printPyInstallerArguments(data_args, PyInstallerArgs)

PyInstaller.__main__.run([appFilename, *data_args, *PyInstallerArgs])

executable = os.path.join(distribution, appName + '.app')
if verbose > 0:
print('Exported application is in', executable)

if dmgFilename:
with tempfile.TemporaryDirectory() as tempdir:
shutil.copytree(executable, os.path.join(tempdir, appName + '.app'))
hdiutil_cmd = ['hdiutil', 'create', '-srcfolder', tempdir,
'-volname', appName, '-format', 'UDZO', dmgFilename]
dmgsign_cmd = ['codesign', '-s', sign_identity, dmgFilename]
if verbose > 0:
dmgsign_cmd[-1:-1] = ['-v']
commands = [hdiutil_cmd, dmgsign_cmd] if sign_identity else [
hdiutil_cmd]
if verbose > 1:
print('About to run the following command sequence:')
for cmd in commands:
print(' ', ' '.join(commandLineArg(x) for x in cmd))
results = [
subprocess.run(cmd, capture_output=True) for cmd in commands]
if verbose > 0 or any(result.returncode != 0 for result in results):
for cmd, result in zip(commands, results):
print('=' * 77, '\nExecution of',
' '.join(commandLineArg(x) for x in cmd),
'returned code', result.returncode,
'success!' if result.returncode == 0 else 'error!')
for msg in (result.stdout, '-' * 77, result.stderr):
text = (msg if isinstance(msg, str) else msg.decode()).strip()
if text:
print(text)
for cmd, result in zip(commands, results):
if result.returncode != 0:
raise Exception(
'Exit code {} during: {}'.format(
result.returncode,
' '.join(commandLineArg(x) for x in cmd)))

if verbose > 0:
print('Created disk image', dmgFilename)

if not keep:
os.remove(appFilename)
elif verbose > 0:
print('Kept application in', appFilename)

if __name__ == '__main__':
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
'-n', '--name', default='DatastructureVisualizations',
help='Base name of execcutable')
parser.add_argument(
'-s', '--source', default='.',
help='Directory of source files and PNG images')
parser.add_argument(
'-i', '--icon', default='design/Datastructure-Visualizations-icon.icns',
help='Path to icon file (relative to directory with visualizaion apps)')
parser.add_argument(
'--version-file', default='version.json',
help='Name of JSON file containing the major and minor version numbers')
parser.add_argument(
'-I', '--ID', default='com.shakumant.dev.{name}',
help='Bundle ID for macOS. Can contain {name} string to be replaced with'
'the base name of the executable.')
parser.add_argument(
'--disk-image', default='{name}{version}.dmg',
help='Disk image (dmg) name. Can contain {name} string to be replaced '
'with the base name of the executable and {version} in _major_minor '
'format.')
parser.add_argument(
'--sign-identity', default='Apple Distribution',
help='Signer identity (common name of codesign certificate)')
parser.add_argument(
'-k', '--keep', default=False, action='store_true',
help='Keep executable source code file created for export.')
parser.add_argument(
'-b', '--backup', default='.bak',
help='File extension for backups of last export')
parser.add_argument(
'-w', '--work-dir', default='./build',
help='Directory for work files, .log, .pyz and etc.')
parser.add_argument(
'-d', '--distribution', default='./dist',
help='Name of export distribution directory')
parser.add_argument(
'-v', '--verbose', action='count', default=0,
help='Add verbose comments')
args = parser.parse_args()

export_macOS(
args.name, version_file=args.version_file,
source_directory=args.source, icon=args.icon, ID=args.ID,
disk_image=args.disk_image, sign_identity=args.sign_identity,
keep=args.keep, backup=args.backup, work_dir=args.work_dir,
distribution=args.distribution, verbose=args.verbose)
Loading