 9ce7c52a10
			
		
	
	
		9ce7c52a10
		
	
	
	
	
		
			
			This includes mainly fixes of string literals using f-strings or .format(...), as well as unpacking of list comprehensions.
		
			
				
	
	
		
			259 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
	
		
			8.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| import argparse
 | |
| import glob
 | |
| import os
 | |
| import shutil
 | |
| import tempfile
 | |
| from contextlib import contextmanager
 | |
| 
 | |
| import crayons
 | |
| import setuptools.sandbox
 | |
| import twine.commands.upload
 | |
| 
 | |
| REPO_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | |
| 
 | |
| 
 | |
| @contextmanager
 | |
| def cd(newdir):
 | |
|     prevdir = os.getcwd()
 | |
|     os.chdir(os.path.expanduser(newdir))
 | |
|     try:
 | |
|         yield
 | |
|     finally:
 | |
|         os.chdir(prevdir)
 | |
| 
 | |
| 
 | |
| def _generate_dist(dist_type, setup_file, package_name, setup_args):
 | |
|     message = "Generating {dist_type} for {package_name}.".format(
 | |
|         dist_type=dist_type,
 | |
|         package_name=package_name,
 | |
|     )
 | |
|     print(crayons.white(message, bold=True))
 | |
| 
 | |
|     setup_dir = os.path.dirname(setup_file)
 | |
|     with cd(setup_dir):
 | |
|         setuptools.sandbox.run_setup(setup_file, setup_args)
 | |
| 
 | |
|     message = "{dist_type} for {package_name} generated under {dir}.\n".format(
 | |
|         dist_type=dist_type,
 | |
|         package_name=package_name,
 | |
|         dir=setup_dir,
 | |
|     )
 | |
|     print(crayons.green(message, bold=True))
 | |
| 
 | |
| 
 | |
| def generate_bdist_wheel(setup_file, package_name, universal=False):
 | |
|     if universal:
 | |
|         _generate_dist("bdist_wheel", setup_file, package_name, ["bdist_wheel", "--universal"])
 | |
|     else:
 | |
|         _generate_dist("bdist_wheel", setup_file, package_name, ["bdist_wheel"])
 | |
| 
 | |
| 
 | |
| def twine_upload(dist_dirs):
 | |
|     message = "Uploading distributions under the following directories:"
 | |
|     print(crayons.green(message, bold=True))
 | |
|     for dist_dir in dist_dirs:
 | |
|         print(crayons.yellow(dist_dir))
 | |
|     twine.commands.upload.main(dist_dirs)
 | |
| 
 | |
| 
 | |
| def cleanup(package_dir):
 | |
|     build_dir = os.path.join(package_dir, "build")
 | |
|     temp_dir = os.path.join(package_dir, "temp")
 | |
|     dist_dir = os.path.join(package_dir, "dist")
 | |
|     egg_info = os.path.join(package_dir, f"{os.path.basename(package_dir)}.egg-info")
 | |
| 
 | |
|     def _rm_if_it_exists(directory):
 | |
|         if os.path.isdir(directory):
 | |
|             print(crayons.green(f"Removing {directory}/*", bold=True))
 | |
|             shutil.rmtree(directory)
 | |
| 
 | |
|     _rm_if_it_exists(build_dir)
 | |
|     _rm_if_it_exists(temp_dir)
 | |
|     _rm_if_it_exists(dist_dir)
 | |
|     _rm_if_it_exists(egg_info)
 | |
| 
 | |
| 
 | |
| def set_variable(fp, variable, value):
 | |
|     fh, temp_abs_path = tempfile.mkstemp()
 | |
|     with os.fdopen(fh, "w") as new_file, open(fp) as old_file:
 | |
|         for line in old_file:
 | |
|             if line.startswith(variable):
 | |
|                 if isinstance(value, bool):
 | |
|                     template = "{variable} = {value}\n"
 | |
|                 else:
 | |
|                     template = '{variable} = "{value}"\n'
 | |
|                 new_file.write(template.format(variable=variable, value=value))
 | |
|             else:
 | |
|                 new_file.write(line)
 | |
| 
 | |
|     os.remove(fp)
 | |
|     shutil.move(temp_abs_path, fp)
 | |
| 
 | |
|     message = f"Set {variable} in {fp} to {value}."
 | |
|     print(crayons.white(message, bold=True))
 | |
| 
 | |
| 
 | |
| def update_requirements_in_zulip_repo(zulip_repo_dir, version, hash_or_tag):
 | |
|     common = os.path.join(zulip_repo_dir, "requirements", "common.in")
 | |
|     prod = os.path.join(zulip_repo_dir, "requirements", "prod.txt")
 | |
|     dev = os.path.join(zulip_repo_dir, "requirements", "dev.txt")
 | |
| 
 | |
|     def _edit_reqs_file(reqs, zulip_bots_line, zulip_line):
 | |
|         fh, temp_abs_path = tempfile.mkstemp()
 | |
|         with os.fdopen(fh, "w") as new_file, open(reqs) as old_file:
 | |
|             for line in old_file:
 | |
|                 if "python-zulip-api" in line and "zulip==" in line:
 | |
|                     new_file.write(zulip_line)
 | |
|                 elif "python-zulip-api" in line and "zulip_bots" in line:
 | |
|                     new_file.write(zulip_bots_line)
 | |
|                 else:
 | |
|                     new_file.write(line)
 | |
| 
 | |
|         os.remove(reqs)
 | |
|         shutil.move(temp_abs_path, reqs)
 | |
| 
 | |
|     url_zulip = "git+https://github.com/zulip/python-zulip-api.git@{tag}#egg={name}=={version}_git&subdirectory={name}\n"
 | |
|     url_zulip_bots = "git+https://github.com/zulip/python-zulip-api.git@{tag}#egg={name}=={version}+git&subdirectory={name}\n"
 | |
|     zulip_bots_line = url_zulip_bots.format(tag=hash_or_tag, name="zulip_bots", version=version)
 | |
|     zulip_line = url_zulip.format(tag=hash_or_tag, name="zulip", version=version)
 | |
| 
 | |
|     _edit_reqs_file(prod, zulip_bots_line, zulip_line)
 | |
|     _edit_reqs_file(dev, zulip_bots_line, zulip_line)
 | |
| 
 | |
|     editable_zulip = f'-e "{url_zulip.rstrip()}"\n'
 | |
|     editable_zulip_bots = f'-e "{url_zulip_bots.rstrip()}"\n'
 | |
| 
 | |
|     _edit_reqs_file(
 | |
|         common,
 | |
|         editable_zulip_bots.format(tag=hash_or_tag, name="zulip_bots", version=version),
 | |
|         editable_zulip.format(tag=hash_or_tag, name="zulip", version=version),
 | |
|     )
 | |
| 
 | |
|     message = "Updated zulip API package requirements in the main repo."
 | |
|     print(crayons.white(message, bold=True))
 | |
| 
 | |
| 
 | |
| def parse_args():
 | |
|     usage = """
 | |
| Script to automate the PyPA release of the zulip, zulip_bots and
 | |
| zulip_botserver packages.
 | |
| 
 | |
| For example, to make a release for version 0.4.0, execute the
 | |
| following steps in order:
 | |
| 
 | |
| 1. Run ./tools/provision
 | |
| 
 | |
| 2. Activate the virtualenv created by tools/provision
 | |
| 
 | |
| 3. To make a release for version 0.4.0, run the
 | |
|    following command:
 | |
| 
 | |
|      ./tools/release-packages --build 0.4.0 --release
 | |
| 
 | |
| 4. After Step 3, commit the outstanding changes in your python-zulip-api
 | |
|    repo.
 | |
| 
 | |
| 5. Create a release tag "0.4.0".
 | |
| 
 | |
| 6. Push the commit and the release tag.
 | |
| 
 | |
| 7. To update the zulip/requirements/* in the main zulip repo, run (this
 | |
|    will update the requirements to install the packages off of the release
 | |
|    tag "0.4.0"):
 | |
| 
 | |
|      ./tools/release-packages update-main-repo PATH_TO_ZULIP_DIR 0.4.0
 | |
| 
 | |
|    You can also update the requirements to install the packages from a
 | |
|    specific commit, like so:
 | |
| 
 | |
|      ./tools/release-packages update-main-repo PATH_TO_ZULIP_DIR 0.4.0 --hash abcedef
 | |
| 
 | |
| 8. Commit and push the outstanding changes in your zulip/ repo.
 | |
| 
 | |
| And you're done! Congrats!
 | |
| """
 | |
|     parser = argparse.ArgumentParser(usage=usage)
 | |
| 
 | |
|     parser.add_argument(
 | |
|         "--cleanup",
 | |
|         "-c",
 | |
|         action="store_true",
 | |
|         default=False,
 | |
|         help="Remove build directories (dist/, build/, egg-info/, etc).",
 | |
|     )
 | |
| 
 | |
|     parser.add_argument(
 | |
|         "--build",
 | |
|         "-b",
 | |
|         metavar="VERSION_NUM",
 | |
|         help=(
 | |
|             "Build sdists and wheels for all packages with the"
 | |
|             "specified version number."
 | |
|             " sdists and wheels are stored in <package_name>/dist/*."
 | |
|         ),
 | |
|     )
 | |
| 
 | |
|     parser.add_argument(
 | |
|         "--release",
 | |
|         "-r",
 | |
|         action="store_true",
 | |
|         default=False,
 | |
|         help="Upload the packages to PyPA using twine.",
 | |
|     )
 | |
| 
 | |
|     subparsers = parser.add_subparsers(dest="subcommand")
 | |
|     parser_main_repo = subparsers.add_parser(
 | |
|         "update-main-repo", help="Update the zulip/requirements/* in the main zulip repo."
 | |
|     )
 | |
|     parser_main_repo.add_argument("repo", metavar="PATH_TO_ZULIP_DIR")
 | |
|     parser_main_repo.add_argument("version", metavar="version number of the packages")
 | |
|     parser_main_repo.add_argument("--hash", metavar="COMMIT_HASH")
 | |
| 
 | |
|     return parser.parse_args()
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     options = parse_args()
 | |
| 
 | |
|     glob_pattern = os.path.join(REPO_DIR, "*", "setup.py")
 | |
|     setup_py_files = glob.glob(glob_pattern)
 | |
| 
 | |
|     if options.cleanup:
 | |
|         package_dirs = map(os.path.dirname, setup_py_files)
 | |
|         for package_dir in package_dirs:
 | |
|             cleanup(package_dir)
 | |
| 
 | |
|     if options.build:
 | |
|         package_dirs = map(os.path.dirname, setup_py_files)
 | |
|         for package_dir in package_dirs:
 | |
|             cleanup(package_dir)
 | |
| 
 | |
|         zulip_init = os.path.join(REPO_DIR, "zulip", "zulip", "__init__.py")
 | |
|         set_variable(zulip_init, "__version__", options.build)
 | |
|         bots_setup = os.path.join(REPO_DIR, "zulip_bots", "setup.py")
 | |
|         set_variable(bots_setup, "ZULIP_BOTS_VERSION", options.build)
 | |
|         set_variable(bots_setup, "IS_PYPA_PACKAGE", True)
 | |
|         botserver_setup = os.path.join(REPO_DIR, "zulip_botserver", "setup.py")
 | |
|         set_variable(botserver_setup, "ZULIP_BOTSERVER_VERSION", options.build)
 | |
| 
 | |
|         for setup_file in setup_py_files:
 | |
|             package_name = os.path.basename(os.path.dirname(setup_file))
 | |
|             generate_bdist_wheel(setup_file, package_name)
 | |
| 
 | |
|         set_variable(bots_setup, "IS_PYPA_PACKAGE", False)
 | |
| 
 | |
|     if options.release:
 | |
|         dist_dirs = glob.glob(os.path.join(REPO_DIR, "*", "dist", "*"))
 | |
|         twine_upload(dist_dirs)
 | |
| 
 | |
|     if options.subcommand == "update-main-repo":
 | |
|         if options.hash:
 | |
|             update_requirements_in_zulip_repo(options.repo, options.version, options.hash)
 | |
|         else:
 | |
|             update_requirements_in_zulip_repo(options.repo, options.version, options.version)
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 |