Skip to content

Commit

Permalink
chore: updating setup.py to understand constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
deborahgu committed Jul 30, 2024
1 parent 3235d4e commit 0b2a730
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 51 deletions.
18 changes: 6 additions & 12 deletions i18n/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
"""
Tool to be used by other IDAs for internationalization.
"""

import argparse
import sys

from . import config

__version__ = '1.6.1'
__version__ = "1.6.2"


class Runner:
"""
Runner class for internationalization.
"""

def __init__(self):
self.args = sys.argv[1:]
self.configuration = None
self.parser = argparse.ArgumentParser()
self.parser.add_argument(
'--config',
'-c',
help='configuration file'
)
self.parser.add_argument(
'-v', '--verbose',
action='count', default=0,
help="Turns on info-level logging."
)
self.parser.add_argument("--config", "-c", help="configuration file")
self.parser.add_argument("-v", "--verbose", action="count", default=0, help="Turns on info-level logging.")
self.add_args()

def add_args(self):
Expand All @@ -45,6 +39,6 @@ def __call__(self, **kwargs):
args = self.parser.parse_known_args(self.args)[0]
for key, val in kwargs.items():
setattr(args, key, val)
root_dir = kwargs.get('root_dir')
root_dir = kwargs.get("root_dir")
self.configuration = config.Configuration(filename=args.config, root_dir=root_dir)
return self.run(args)
115 changes: 76 additions & 39 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,81 @@
#!/usr/bin/env python
import os
import re
import pathlib
import re

from setuptools import setup


def load_requirements(*requirements_paths):
def load_requirements(*requirements_paths) -> list[str]:
"""
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 = set()
requirements = {}
constraint_files = set()

# groups "my-package-name<=x.y.z,..." into ("my-package-name", "<=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)
# it's fine to add constraints to an unconstrained package, but 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

# process .in files and store the path to any constraint files that are pulled in
for path in requirements_paths:
with open(path) as reqs:
requirements.update(
line.split('#')[0].strip() for line in reqs
if is_requirement(line.strip())
)
return list(requirements)
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 and add any new constraints found 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;
that is, it is not blank, a comment, a URL, or an included file.
"""
return line and not line.startswith(('-r', '#', '-e', 'git+', '-c'))
return line and not line.startswith(("-r", "#", "-e", "git+", "-c"))


def get_version(*file_paths):
"""
Extract the version string from the file at the given relative path fragments.
"""
filename = os.path.join(os.path.dirname(__file__), *file_paths)
version_file = open(filename).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.")
"""
Extract the version string from the file at the given relative path fragments.
"""
filename = os.path.join(os.path.dirname(__file__), *file_paths)
version_file = open(filename).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.")


VERSION = get_version("i18n", "__init__.py")
Expand All @@ -49,34 +86,34 @@ def get_version(*file_paths):
long_description = (here / "README.rst").read_text(encoding="utf-8")

setup(
name='edx-i18n-tools',
name="edx-i18n-tools",
version=VERSION,
description='edX Internationalization Tools',
description="edX Internationalization Tools",
long_description=long_description,
long_description_content_type='text/x-rst',
author='edX',
author_email='[email protected]',
url='https://github.com/openedx/i18n-tools',
long_description_content_type="text/x-rst",
author="edX",
author_email="[email protected]",
url="https://github.com/openedx/i18n-tools",
packages=[
'i18n',
"i18n",
],
install_requires=load_requirements('requirements/base.in'),
install_requires=load_requirements("requirements/base.in"),
entry_points={
'console_scripts': [
'i18n_tool = i18n.main:main',
"console_scripts": [
"i18n_tool = i18n.main:main",
],
},
license='Apache License 2.0',
license="Apache License 2.0",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.11',
'Framework :: Django',
'Framework :: Django :: 4.2',
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.11",
"Framework :: Django",
"Framework :: Django :: 4.2",
],
)

0 comments on commit 0b2a730

Please sign in to comment.