From d7ff38bf682c519293b022bcb3b04be078cc744e Mon Sep 17 00:00:00 2001 From: Agrendalath Date: Wed, 17 Jan 2024 03:26:54 +0100 Subject: [PATCH] build: improve `setup.py`, bump version --- image_explorer/__init__.py | 4 +- setup.py | 111 ++++++++++++++++++++++++++++++++++--- 2 files changed, 104 insertions(+), 11 deletions(-) diff --git a/image_explorer/__init__.py b/image_explorer/__init__.py index 3f66b9a..51a5d59 100644 --- a/image_explorer/__init__.py +++ b/image_explorer/__init__.py @@ -20,6 +20,6 @@ """ Image Explorer XBlock """ -from __future__ import absolute_import - from .image_explorer import ImageExplorerBlock + +__version__ = '2.2.0' diff --git a/setup.py b/setup.py index 7128052..28d9ac8 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,89 @@ # -*- coding: utf-8 -*- -# Imports ########################################################### - import os +import re +import sys + from setuptools import setup -# Functions ######################################################### +def load_requirements(*requirements_paths): + """ + Load all requirements from the specified requirements files. + Requirements will include any constraints from files specified + with -c in the requirements files. + Returns a list of requirement strings. + """ + requirements = {} + constraint_files = set() + + # groups "pkg<=x.y.z,..." into ("pkg", "<=x.y.z,...") + requirement_line_regex = re.compile(r"([a-zA-Z0-9-_.\[\]]+)([<>=][^#\s]+)?") + + def add_version_constraint_or_raise(current_line, current_requirements, add_if_not_present): + regex_match = requirement_line_regex.match(current_line) + if regex_match: + package = regex_match.group(1) + version_constraints = regex_match.group(2) + existing_version_constraints = current_requirements.get(package, None) + # fine to add constraints to an unconstrained package, + # raise an error if there are already constraints in place + if existing_version_constraints and existing_version_constraints != version_constraints: + raise BaseException( + f'Multiple constraint definitions found for {package}:' + f' "{existing_version_constraints}" and "{version_constraints}".' + f'Combine constraints into one location with {package}' + f'{existing_version_constraints},{version_constraints}.' + ) + if add_if_not_present or package in current_requirements: + current_requirements[package] = version_constraints + + # read requirements from .in + # store the path to any constraint files that are pulled in + for path in requirements_paths: + with open(path) as reqs: + for line in reqs: + if is_requirement(line): + add_version_constraint_or_raise(line, requirements, True) + if line and line.startswith('-c') and not line.startswith('-c http'): + constraint_files.add(os.path.dirname(path) + '/' + line.split('#')[0].replace('-c', '').strip()) + + # process constraint files: add constraints to existing requirements + for constraint_file in constraint_files: + with open(constraint_file) as reader: + for line in reader: + if is_requirement(line): + add_version_constraint_or_raise(line, requirements, False) + + # process back into list of pkg><=constraints strings + constrained_requirements = [f'{pkg}{version or ""}' for (pkg, version) in sorted(requirements.items())] + return constrained_requirements + + +def is_requirement(line): + """ + Return True if the requirement line is a package requirement. + Returns: + bool: True if the line is not blank, a comment, + a URL, or an included file + """ + return line and line.strip() and not line.startswith(("-r", "#", "-e", "git+", "-c")) + + +def get_version(*file_paths): + """ + Extract the version string from the file. + Input: + - file_paths: relative path fragments to file with + version string + """ + filename = os.path.join(os.path.dirname(__file__), *file_paths) + version_file = open(filename, encoding="utf8").read() + version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M) + if version_match: + return version_match.group(1) + raise RuntimeError('Unable to find version string.') + def package_data(pkg, root_list): """Generic function to find package_data for `pkg` under `root`.""" @@ -19,19 +96,35 @@ def package_data(pkg, root_list): return {pkg: data} -# Main ############################################################## +VERSION = get_version('image_explorer', '__init__.py') + +if sys.argv[-1] == 'tag': + print("Tagging the version on GitHub:") + os.system("git tag -a %s -m 'version %s'" % (VERSION, VERSION)) + os.system("git push --tags") + sys.exit() + +README = open(os.path.join(os.path.dirname(__file__), 'README.md'), encoding="utf8").read() setup( name='xblock-image-explorer', - version='2.1.0', + version=VERSION, description='XBlock - Image Explorer', - packages=['image_explorer'], - install_requires=[ - 'XBlock>=1.2', - 'parsel>=1.6.0,<=1.6.0', + long_description=README, + long_description_content_type='text/markdown', + classifiers=[ + 'Programming Language :: Python', + 'Programming Language :: Python :: 3.8', + 'Framework :: Django', + 'Framework :: Django :: 3.2', + 'Framework :: Django :: 4.2', ], + url='https://github.com/openedx/xblock-image-explorer', + install_requires=load_requirements('requirements/base.in'), entry_points={ 'xblock.v1': 'image-explorer = image_explorer:ImageExplorerBlock', }, + packages=['image_explorer'], package_data=package_data("image_explorer", ["static", "templates", "public", "translations"]), + python_requires=">=3.8", )