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

use hatch for building #1429

Merged
merged 2 commits into from
Sep 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
302 changes: 58 additions & 244 deletions dist/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,30 +45,27 @@
12. zip up documentation/build/html and get ready to upload/delete it.
Rename to music21.v.7.1.0-docs.zip (skip for Alpha/Beta)

12b. If any new file extensions have been added, be sure to add them to MANIFEST.in
13. Run "hatch build" -- requires hatch to be installed "brew install hatch"

13. And finally this file. (from the command line; not as python -m...; cwd must
be music21[base]/dist/ )
There are major problems in SetupTools -- v8 (or even a 7.3.1) needs to
fix them -- creating a dir music21.egg-info in the main dir with a
requires.txt file created as root.
14. Run this file -- it builds the no-corpus version of music21.
DO NOT RUN THIS ON A PC -- the Mac .tar.gz might have an incorrect permission if you do.

14. COMMIT to GitHub at this point w/ commit comment of the new version,
15. COMMIT to GitHub at this point w/ commit comment of the new version,
then don't change anything until the next step is done.
(.gitignore will avoid uploading the large files created here...)

15. Tag the commit: git tag -a vX.Y.Z -m "music21 vX.Y.Z"
16. Tag the commit: git tag -a vX.Y.Z -m "music21 vX.Y.Z"
Don't forget the "v" in the release tag.
Sanity check that the correct commit was tagged: git log

16. Push tags: git push upstream --tags
17. Push tags: git push upstream --tags

17. Create a new release on GitHub and upload the TWO files created here and docs.
18. Create a new release on GitHub and upload the TWO files created here and docs.
Drag in this order: .tar.gz, documentation, no-corpus.tar.gz

Finish this before doing the next step, even though it looks like it could be done in parallel.

18. Upload the new file to PyPI with "twine upload music21-7.3.5a2.tar.gz" [*]
19. Upload the new file to PyPI with "twine upload music21-7.3.5a2.tar.gz" [*]

[*] Requires twine to be installed

Expand All @@ -82,251 +79,68 @@
username:your_username
password:your_password

19. Delete the two .tar.gz files in dist...
20. Delete the two .tar.gz files in dist...

20. For starting a new major release create a GitHub branch for the old one.
21. For starting a new major release create a GitHub branch for the old one.

21. Immediately increment the number in _version.py and run tests on it here
22. Immediately increment the number in _version.py and run tests on it here
to prepare for next release.

22. Announce on the blog, to the list, and twitter.

DO NOT RUN THIS ON A PC -- the Mac .tar.gz has an incorrect permission if you do.
23. Announce on the blog, to the list, and twitter.
'''
import hashlib
import os
import sys
import shutil
import tarfile

from music21 import base
from music21 import common

from music21 import environment
environLocal = environment.Environment('..dist.dist')

PY = sys.executable
environLocal.warn(f'using python executable at {PY}')

class Distributor:
def __init__(self):
# self.fpEgg = None
# self.fpWin = None
self.fpTar = None

self.buildNoCorpus = True
# self.fpEggNoCorpus = None
self.fpTarNoCorpus = None

self.version = base.VERSION_STR

self._initPaths()

def _initPaths(self):

# must be in the dist dir
directory = os.getcwd()
parentDir = os.path.dirname(directory)
parentContents = sorted(os.listdir(parentDir))
# make sure we are in the proper directory
if (not directory.endswith('dist')
or 'music21' not in parentContents):
raise Exception(f'not in the music21{os.sep}dist directory: {directory}')

self.fpDistDir = directory
self.fpPackageDir = parentDir # dir with setup.py
self.fpBuildDir = os.path.join(self.fpPackageDir, 'build')
# self.fpEggInfo = os.path.join(self.fpPackageDir, 'music21.egg-info')

sys.path.insert(0, parentDir) # to get setup in as a possibility.

for fp in [self.fpDistDir, self.fpPackageDir, self.fpBuildDir]:
environLocal.warn(fp)


def updatePaths(self):
'''
Process output of build scripts. Get most recently produced distributions.
'''
contents = sorted(os.listdir(self.fpDistDir))
for fn in contents:
fp = os.path.join(self.fpDistDir, fn)
# if self.version in fn and fn.endswith('.egg'):
# self.fpEgg = fp
# if self.version in fn and fn.endswith('.exe'):
# fpNew = fp.replace('.macosx-10.8-intel.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.8-x86_64.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.9-intel.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.9-x86_64.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.10-intel.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.10-x86_64.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.11-intel.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.11-x86_64.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.12-intel.exe', '.win32.exe')
# fpNew = fpNew.replace('.macosx-10.12-x86_64.exe', '.win32.exe')
# if fpNew != fp:
# os.rename(fp, fpNew)
# self.fpWin = fpNew

print(fn)
if self.version in fn and fn.endswith('.tar.gz'):
self.fpTar = fp
else:
environLocal.warn(fn + ' does not end with .tar.gz')

environLocal.warn('giving path for tar.gz')
for fn in [self.fpTar]:
if fn is None:
environLocal.warn('missing fn path')
else:
environLocal.warn(fn)

def removeCorpus(self, fp):
'''
Remove the corpus from a compressed file (.tar.gz) and
create a new music21-noCorpus version.

Return the completed file path of the newly created edition.

NOTE: this function works only with Posix systems.
'''
TAR = 'TAR'
# EGG = 'EGG'
if fp and fp.endswith('.tar.gz'):
mode = TAR
modeExt = '.tar.gz'
else:
raise Exception('incorrect source file path')

fpDir, fn = os.path.split(fp)

# this has .tar.gz extension; this is the final completed package
fnDst = fn.replace('music21', 'music21-noCorpus')
fpDst = os.path.join(fpDir, fnDst)
# remove file extensions
fnDstDir = fnDst.replace(modeExt, '')
fpDstDir = os.path.join(fpDir, fnDstDir)

# get the name of the dir after decompression
fpSrcDir = os.path.join(fpDir, fn.replace(modeExt, ''))

# remove old dirs if it exists
if os.path.exists(fpDst):
shutil.rmtree(fpDst)

if os.path.exists(fpDstDir):
shutil.rmtree(fpDstDir)

if mode == TAR:
tf = tarfile.open(fp, 'r:gz')
# the path here is the dir into which to expand,
# not the name of that dir
tf.extractall(path=fpDir)
os.system(f'mv {fpSrcDir} {fpDstDir}')
tf.close() # done after extraction

# elif mode == EGG:
# os.system(f'mkdir {fpDstDir}')
# # need to create dst dir to unzip into
# tf = zipfile.ZipFile(fp, 'r')
# tf.extractall(path=fpDstDir)


# remove files, updates manifest
for fn in common.getCorpusContentDirs():
fp = os.path.join(fpDstDir, 'music21', 'corpus', fn)
shutil.rmtree(fp)

fp = os.path.join(fpDstDir, 'music21', 'corpus', '_metadataCache')
from music21._version import __version__ as version
from music21.common.pathTools import getRootFilePath, getCorpusContentDirs

def removeCorpus():
'''
Remove the corpus from a compressed file (.tar.gz) and
create a new music21-noCorpus version.

Return the completed file path of the newly created edition.

NOTE: this function works only with Posix systems.
'''
fp = getRootFilePath() / 'dist' / ('music21-' + version + '.tar.gz')
fpDir, fn = os.path.split(str(fp))

# this has .tar.gz extension; this is the final completed package
fnDst = fn.replace('music21', 'music21-noCorpus')
fpDst = os.path.join(fpDir, fnDst)
# remove file extensions
fnDstDir = fnDst.replace('.tar.gz', '')
fpDstDir = os.path.join(fpDir, fnDstDir)

file = tarfile.open(fp)
file.extractall(fpDir)
file.close()

os.rename(fpDstDir.replace('-noCorpus', ''), fpDstDir)

# remove files, updates manifest
for fn in getCorpusContentDirs():
fp = os.path.join(fpDstDir, 'music21', 'corpus', fn)
shutil.rmtree(fp)

# adjust the sources Txt file
# if mode == TAR:
sourcesTxt = os.path.join(fpDstDir, 'music21.egg-info', 'SOURCES.txt')
# else:
# raise Exception('invalid mode')

# elif mode == EGG:
# sourcesTxt = os.path.join(fpDstDir, 'EGG-INFO', 'SOURCES.txt')

# files will look like 'music21/corpus/haydn' in SOURCES.txt
post = []
f = open(sourcesTxt, 'r')
corpusContentDirs = common.getCorpusContentDirs()
for line in f:
match = False
if 'corpus' in line:
for fn in corpusContentDirs:
# these are relative paths
fp = os.path.join('music21', 'corpus', fn)
if line.startswith(fp):
match = True
break
if not match:
post.append(line)
f.close()
f = open(sourcesTxt, 'w')
f.writelines(post)
f.close()

if mode == TAR:
# compress dst dir to dst file path name
# need the -C flag to set relative dir
# just name of dir
cmd = f'tar -C {fpDir} -czf {fpDst} {fnDstDir}/'
os.system(cmd)

# remove directory that was compressed
if os.path.exists(fpDstDir):
shutil.rmtree(fpDstDir)

return fpDst # full path with extension



def build(self):
'''
Build all distributions. Update and rename file paths if necessary;
remove extract build products.
'''
# call setup.py
# import setup # -- for some reason does not work unless called from command line
for buildType in ['sdist --formats=gztar', 'bdist_wheel']:
environLocal.warn(f'making {buildType}')

savePath = os.getcwd()
os.chdir(self.fpPackageDir)
os.system(f'{PY} setup.py {buildType}')
os.chdir(savePath)

self.updatePaths()

environLocal.warn(f'removing {self.fpBuildDir} (except on windows...there do it yourself)')
try:
shutil.rmtree(self.fpBuildDir)
except FileNotFoundError:
environLocal.warn(
'Directory was already cleaned up'
)

if self.buildNoCorpus is True:
# create no corpus versions
self.fpTarNoCorpus = self.removeCorpus(fp=self.fpTar)
# self.fpEggNoCorpus = self.removeCorpus(fp=self.fpEgg)


def md5ForFile(self, path, hexReturn=True):
if hexReturn:
return hashlib.md5(open(path, 'rb').read()).hexdigest()
else:
return hashlib.md5(open(path, 'rb').read()).digest()
fp = os.path.join(fpDstDir, 'music21', 'corpus', '_metadataCache')
shutil.rmtree(fp)

# compress dst dir to dst file path name
# need the -C flag to set relative dir
# just name of dir
cmd = f'tar -C {fpDir} -czf {fpDst} {fnDstDir}/'
os.system(cmd)

# # remove directory that was compressed
if os.path.exists(fpDstDir):
shutil.rmtree(fpDstDir)

return fpDst # full path with extension


# ------------------------------------------------------------------------------
if __name__ == '__main__':
d = Distributor()
d.buildNoCorpus = True
d.build()
d.updatePaths()
# d.getMD5Path()
# d.uploadPyPi()
removeCorpus()
27 changes: 19 additions & 8 deletions music21/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,25 @@
Changing this number invalidates old pickles -- do it if the old pickles create a problem.
'''

__version_info__ = (8, 0, 0, 'rc1') # can be 3-tuple or 4+-tuple: (7, 0, 5, 'a2')
def get_version_tuple(vv):
v = vv.split('.')
last_v = v[-1]
v[-1] = ''
beta = ''
in_patch = True
for ch in last_v:
if in_patch and ch.isdigit():
v[-1] += ch
else:
in_patch = False
beta += ch
if beta:
v.append(beta)
return tuple(v)

v = '.'.join(str(x) for x in __version_info__[0:3])
if len(__version_info__) > 3 and __version_info__[3]: # type: ignore
v += __version_info__[3] # type: ignore
if len(__version_info__) > 4:
v += '.' + '.'.join(__version_info__[4:])

__version__ = v
__version__ = '8.0.0rc2'

del v
__version_info__ = get_version_tuple(__version__)

del get_version_tuple
2 changes: 1 addition & 1 deletion music21/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<class 'music21.base.Music21Object'>

>>> music21.VERSION_STR
'8.0.0rc1'
'8.0.0rc2'

Alternatively, after doing a complete import, these classes are available
under the module "base":
Expand Down
Loading