hassle.hassle

  1import argparse
  2import os
  3import shutil
  4from pathlib import Path
  5
  6import tomlkit
  7
  8from hassle import hassle_utilities
  9from hassle.generate_tests import generate_test_files
 10from hassle.run_tests import run_tests
 11
 12root = Path(__file__).parent
 13
 14
 15def get_args() -> argparse.Namespace:
 16    parser = argparse.ArgumentParser()
 17
 18    parser.add_argument(
 19        "package",
 20        type=str,
 21        default=".",
 22        nargs="?",
 23        help=""" The name of the package or project to use,
 24        assuming it's a subfolder of your current working directory.
 25        Can also be a full path to the package. If nothing is given,
 26        the current working directory will be used.""",
 27    )
 28
 29    parser.add_argument(
 30        "-b", "--build", action="store_true", help=""" Build the package. """
 31    )
 32
 33    parser.add_argument(
 34        "-t",
 35        "--tag_version",
 36        action="store_true",
 37        help=""" Add a git tag corresponding to the version in pyproject.toml. """,
 38    )
 39
 40    parser.add_argument(
 41        "-i",
 42        "--install",
 43        action="store_true",
 44        help=""" Install the package from source. """,
 45    )
 46
 47    parser.add_argument(
 48        "-iv",
 49        "--increment_version",
 50        type=str,
 51        default=None,
 52        help=""" Increment version in pyproject.toml.
 53        Can be one of "major", "minor", or "patch". """,
 54    )
 55
 56    parser.add_argument(
 57        "-p",
 58        "--publish",
 59        action="store_true",
 60        help=""" Publish package to PyPi.
 61        Note: You must have configured twine 
 62        and registered a PyPi account/generated an API
 63        key to use this option.""",
 64    )
 65
 66    parser.add_argument(
 67        "-rt",
 68        "--run_tests",
 69        action="store_true",
 70        help=""" Run tests for the package. """,
 71    )
 72
 73    parser.add_argument(
 74        "-gt",
 75        "--generate_tests",
 76        action="store_true",
 77        help=""" Generate tests for the package. """,
 78    )
 79
 80    parser.add_argument(
 81        "-uc",
 82        "--update_changelog",
 83        action="store_true",
 84        help=""" Update changelog file. """,
 85    )
 86
 87    parser.add_argument(
 88        "-od",
 89        "--overwrite_dependencies",
 90        action="store_true",
 91        help=""" When building a package, packagelister will be used
 92        to update the dependencies list in pyproject.toml.
 93        The default behavior is to append any new dependencies to
 94        the current list so as not to erase any manually added dependencies
 95        that packagelister may not detect. If you don't have any manually 
 96        added dependencies and want to remove any dependencies that your
 97        project no longer uses, pass this flag.""",
 98    )
 99
100    parser.add_argument(
101        "-ca",
102        "--commit_all",
103        type=str,
104        default=None,
105        help=""" Git stage and commit all tracked files
106        with this supplied commit message.
107        If 'build' is passed, all commits will have
108        message: 'chore: build v{current_version}""",
109    )
110
111    parser.add_argument(
112        "-s",
113        "--sync",
114        action="store_true",
115        help=""" Pull from github, then push current commit to repo. """,
116    )
117
118    parser.add_argument(
119        "-dv",
120        "--dependency_versions",
121        action="store_true",
122        help=""" Include version specifiers for dependencies in
123        pyproject.toml.""",
124    )
125
126    parser.add_argument(
127        "-up",
128        "--update",
129        type=str,
130        default=None,
131        help=""" Excpects one argument: "major", "minor", or "patch".
132        Passing "-up minor" is equivalent to passing the cli string: "-b -t -i -iv minor -uc -ca build -s".
133        To publish the updated package, the -p/--publish switch needs to be added to the cli input.""",
134    )
135
136    args = parser.parse_args()
137
138    args.package = Path(args.package).resolve()
139
140    if args.update:
141        args.build = True
142        args.tag_version = True
143        args.install = True
144        args.increment_version = args.update
145        args.update_changelog = True
146        args.commit_all = "build"
147        args.sync = True
148
149    if args.increment_version and args.increment_version not in [
150        "major",
151        "minor",
152        "patch",
153    ]:
154        raise ValueError(
155            f"Invalid option for -iv/--increment_version: {args.increment_version}"
156        )
157
158    if args.commit_all == "":
159        raise ValueError("Commit message for args.commit_all cannot be empty.")
160
161    return args
162
163
164def main(args: argparse.Namespace = None):
165    if not args:
166        args = get_args()
167
168    pyproject_path = args.package / "pyproject.toml"
169
170    if not pyproject_path.exists():
171        raise FileNotFoundError(f"Could not locate pyproject.toml for {args.package}")
172
173    if args.generate_tests:
174        generate_test_files(args.package)
175
176    if args.run_tests:
177        run_tests(args.package)
178
179    if args.increment_version:
180        hassle_utilities.increment_version(pyproject_path, args.increment_version)
181
182    if args.build:
183        try:
184            shutil.rmtree(f"{args.package}/dist")
185        except Exception as e:
186            pass
187        os.system(f"black {args.package}")
188        os.system(f"isort {args.package}")
189        hassle_utilities.update_dependencies(
190            pyproject_path, args.overwrite_dependencies
191        )
192        hassle_utilities.update_minimum_python_version(pyproject_path)
193        hassle_utilities.generate_docs(args.package)
194        os.system(f"py -m build {args.package}")
195
196    if args.update_changelog:
197        hassle_utilities.update_changelog(pyproject_path)
198        # If we're going to add tag for current version
199        # commit changelog first
200        if args.tag_version:
201            os.chdir(args.package)
202            os.system("git add CHANGELOG.md")
203            os.system('git commit CHANGELOG.md -m "chore: update changelog"')
204
205    if args.commit_all:
206        os.chdir(args.package)
207        if args.commit_all == "build":
208            version = tomlkit.loads(pyproject_path.read_text())["project"]["version"]
209            args.commit_all = f"chore: build v{version}"
210        os.system("git add .")
211        os.system(f'git commit -m "{args.commit_all}"')
212
213    if args.tag_version:
214        hassle_utilities.tag_version(args.package)
215
216    if args.publish:
217        os.system(f"twine upload {args.package / 'dist' / '*'}")
218
219    if args.install:
220        os.system(f"pip install {args.package} --no-deps --upgrade --no-cache-dir")
221
222    if args.sync:
223        os.chdir(args.package)
224        os.system(f"git pull --tags origin main")
225        os.system(f"git push origin main:main --tags")
226
227
228if __name__ == "__main__":
229    main(get_args())
def get_args() -> argparse.Namespace:
 16def get_args() -> argparse.Namespace:
 17    parser = argparse.ArgumentParser()
 18
 19    parser.add_argument(
 20        "package",
 21        type=str,
 22        default=".",
 23        nargs="?",
 24        help=""" The name of the package or project to use,
 25        assuming it's a subfolder of your current working directory.
 26        Can also be a full path to the package. If nothing is given,
 27        the current working directory will be used.""",
 28    )
 29
 30    parser.add_argument(
 31        "-b", "--build", action="store_true", help=""" Build the package. """
 32    )
 33
 34    parser.add_argument(
 35        "-t",
 36        "--tag_version",
 37        action="store_true",
 38        help=""" Add a git tag corresponding to the version in pyproject.toml. """,
 39    )
 40
 41    parser.add_argument(
 42        "-i",
 43        "--install",
 44        action="store_true",
 45        help=""" Install the package from source. """,
 46    )
 47
 48    parser.add_argument(
 49        "-iv",
 50        "--increment_version",
 51        type=str,
 52        default=None,
 53        help=""" Increment version in pyproject.toml.
 54        Can be one of "major", "minor", or "patch". """,
 55    )
 56
 57    parser.add_argument(
 58        "-p",
 59        "--publish",
 60        action="store_true",
 61        help=""" Publish package to PyPi.
 62        Note: You must have configured twine 
 63        and registered a PyPi account/generated an API
 64        key to use this option.""",
 65    )
 66
 67    parser.add_argument(
 68        "-rt",
 69        "--run_tests",
 70        action="store_true",
 71        help=""" Run tests for the package. """,
 72    )
 73
 74    parser.add_argument(
 75        "-gt",
 76        "--generate_tests",
 77        action="store_true",
 78        help=""" Generate tests for the package. """,
 79    )
 80
 81    parser.add_argument(
 82        "-uc",
 83        "--update_changelog",
 84        action="store_true",
 85        help=""" Update changelog file. """,
 86    )
 87
 88    parser.add_argument(
 89        "-od",
 90        "--overwrite_dependencies",
 91        action="store_true",
 92        help=""" When building a package, packagelister will be used
 93        to update the dependencies list in pyproject.toml.
 94        The default behavior is to append any new dependencies to
 95        the current list so as not to erase any manually added dependencies
 96        that packagelister may not detect. If you don't have any manually 
 97        added dependencies and want to remove any dependencies that your
 98        project no longer uses, pass this flag.""",
 99    )
100
101    parser.add_argument(
102        "-ca",
103        "--commit_all",
104        type=str,
105        default=None,
106        help=""" Git stage and commit all tracked files
107        with this supplied commit message.
108        If 'build' is passed, all commits will have
109        message: 'chore: build v{current_version}""",
110    )
111
112    parser.add_argument(
113        "-s",
114        "--sync",
115        action="store_true",
116        help=""" Pull from github, then push current commit to repo. """,
117    )
118
119    parser.add_argument(
120        "-dv",
121        "--dependency_versions",
122        action="store_true",
123        help=""" Include version specifiers for dependencies in
124        pyproject.toml.""",
125    )
126
127    parser.add_argument(
128        "-up",
129        "--update",
130        type=str,
131        default=None,
132        help=""" Excpects one argument: "major", "minor", or "patch".
133        Passing "-up minor" is equivalent to passing the cli string: "-b -t -i -iv minor -uc -ca build -s".
134        To publish the updated package, the -p/--publish switch needs to be added to the cli input.""",
135    )
136
137    args = parser.parse_args()
138
139    args.package = Path(args.package).resolve()
140
141    if args.update:
142        args.build = True
143        args.tag_version = True
144        args.install = True
145        args.increment_version = args.update
146        args.update_changelog = True
147        args.commit_all = "build"
148        args.sync = True
149
150    if args.increment_version and args.increment_version not in [
151        "major",
152        "minor",
153        "patch",
154    ]:
155        raise ValueError(
156            f"Invalid option for -iv/--increment_version: {args.increment_version}"
157        )
158
159    if args.commit_all == "":
160        raise ValueError("Commit message for args.commit_all cannot be empty.")
161
162    return args
def main(args: argparse.Namespace = None):
165def main(args: argparse.Namespace = None):
166    if not args:
167        args = get_args()
168
169    pyproject_path = args.package / "pyproject.toml"
170
171    if not pyproject_path.exists():
172        raise FileNotFoundError(f"Could not locate pyproject.toml for {args.package}")
173
174    if args.generate_tests:
175        generate_test_files(args.package)
176
177    if args.run_tests:
178        run_tests(args.package)
179
180    if args.increment_version:
181        hassle_utilities.increment_version(pyproject_path, args.increment_version)
182
183    if args.build:
184        try:
185            shutil.rmtree(f"{args.package}/dist")
186        except Exception as e:
187            pass
188        os.system(f"black {args.package}")
189        os.system(f"isort {args.package}")
190        hassle_utilities.update_dependencies(
191            pyproject_path, args.overwrite_dependencies
192        )
193        hassle_utilities.update_minimum_python_version(pyproject_path)
194        hassle_utilities.generate_docs(args.package)
195        os.system(f"py -m build {args.package}")
196
197    if args.update_changelog:
198        hassle_utilities.update_changelog(pyproject_path)
199        # If we're going to add tag for current version
200        # commit changelog first
201        if args.tag_version:
202            os.chdir(args.package)
203            os.system("git add CHANGELOG.md")
204            os.system('git commit CHANGELOG.md -m "chore: update changelog"')
205
206    if args.commit_all:
207        os.chdir(args.package)
208        if args.commit_all == "build":
209            version = tomlkit.loads(pyproject_path.read_text())["project"]["version"]
210            args.commit_all = f"chore: build v{version}"
211        os.system("git add .")
212        os.system(f'git commit -m "{args.commit_all}"')
213
214    if args.tag_version:
215        hassle_utilities.tag_version(args.package)
216
217    if args.publish:
218        os.system(f"twine upload {args.package / 'dist' / '*'}")
219
220    if args.install:
221        os.system(f"pip install {args.package} --no-deps --upgrade --no-cache-dir")
222
223    if args.sync:
224        os.chdir(args.package)
225        os.system(f"git pull --tags origin main")
226        os.system(f"git push origin main:main --tags")