From 7f90a317ce99e79a568d235372ebb27189757a64 Mon Sep 17 00:00:00 2001 From: Aarif Date: Thu, 4 Jun 2020 16:32:19 +0500 Subject: [PATCH] Add support for python 3.5 --- .travis.yml | 5 +- Makefile | 10 ++++ exporter/check.py | 1 + exporter/config.py | 8 ++-- exporter/course_export.py | 6 ++- exporter/main.py | 4 +- exporter/metrics.py | 1 + exporter/mysql_query.py | 4 +- exporter/properties.py | 4 +- exporter/tasks.py | 47 +++++++++++++++---- exporter/tests/test_main.py | 13 +++-- exporter/tests/test_metrics.py | 1 + exporter/tests/test_tasks.py | 1 + exporter/util.py | 10 ++-- requirements.txt | 20 -------- requirements/base.in | 15 ++++++ requirements/base.txt | 34 ++++++++++++++ requirements/constraints.txt | 1 + .../github.in | 2 + requirements/github.txt | 7 +++ requirements/pip-tools.in | 5 ++ requirements/pip-tools.txt | 12 +++++ requirements/test.in | 10 ++++ requirements/test.txt | 47 +++++++++++++++++++ requirements/tox.in | 3 ++ requirements/tox.txt | 20 ++++++++ test_requirements.txt | 2 - tox.ini | 5 +- 28 files changed, 247 insertions(+), 51 deletions(-) delete mode 100644 requirements.txt create mode 100644 requirements/base.in create mode 100644 requirements/base.txt create mode 100644 requirements/constraints.txt rename github_requirements.txt => requirements/github.in (80%) create mode 100644 requirements/github.txt create mode 100644 requirements/pip-tools.in create mode 100644 requirements/pip-tools.txt create mode 100644 requirements/test.in create mode 100644 requirements/test.txt create mode 100644 requirements/tox.in create mode 100644 requirements/tox.txt delete mode 100644 test_requirements.txt diff --git a/.travis.yml b/.travis.yml index c44c149..92feab9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,13 @@ # Config file for automatic testing at travis-ci.org language: python + matrix: include: - python: 2.7 env: TOXENV=py27 + - python: 3.5 + env: TOXENV=py35 cache: - pip @@ -13,7 +16,7 @@ before_install: - pip install --upgrade pip install: - - pip install -r test_requirements.txt + - pip install -r requirements/tox.txt script: - tox diff --git a/Makefile b/Makefile index e672b4a..d0f7668 100644 --- a/Makefile +++ b/Makefile @@ -4,3 +4,13 @@ clean: test: py.test + + +upgrade: export CUSTOM_COMPILE_COMMAND=make upgrade +upgrade: ## update the requirements/*.txt files with the latest packages satisfying requirements/*.in + pip install -qr requirements/pip-tools.txt + pip-compile --upgrade -o requirements/pip-tools.txt requirements/pip-tools.in + pip-compile --upgrade -o requirements/base.txt requirements/base.in + pip-compile --upgrade -o requirements/test.txt requirements/test.in + pip-compile --upgrade -o requirements/github.txt requirements/github.in + pip-compile --upgrade -o requirements/tox.txt requirements/tox.in diff --git a/exporter/check.py b/exporter/check.py index 2e311e4..1ceecd0 100755 --- a/exporter/check.py +++ b/exporter/check.py @@ -17,6 +17,7 @@ --window= Fail if the most recent file is older than this many days. [default: 6] """ +from __future__ import absolute_import import datetime import logging import os diff --git a/exporter/config.py b/exporter/config.py index 64faad5..99188a4 100644 --- a/exporter/config.py +++ b/exporter/config.py @@ -1,5 +1,6 @@ # pylint: disable=missing-docstring +from __future__ import absolute_import import json import logging import logging.config @@ -10,6 +11,7 @@ import yaml from exporter.util import merge, filter_keys +import six WORK_SUBDIR = 'course-data' @@ -59,7 +61,7 @@ def update_config(config, program_options): def merge_program_options(config, program_options): # get program options, removing '--' and replacing '-' with '_' options = {k[2:].replace('-', '_'): v for k, v - in program_options.iteritems() + in six.iteritems(program_options) if k.startswith('--')} config['options'] = options @@ -104,7 +106,7 @@ def update_environments(config): for env in ['prod', 'edge']: if env in environments: data = environments.get(env, {}) - for config_name, token_name in field_map.iteritems(): + for config_name, token_name in six.iteritems(field_map): data[config_name] = tokens.get(token_name) # different settings for edge @@ -123,7 +125,7 @@ def update_organizations(config): # lowercase orgs before selection organizations = {org.lower(): values for org, values - in config['organizations'].iteritems()} + in six.iteritems(config['organizations'])} # select only organizations in arguments organizations = filter_keys(organizations, values.get('org')) diff --git a/exporter/course_export.py b/exporter/course_export.py index 49efc05..d6a2443 100755 --- a/exporter/course_export.py +++ b/exporter/course_export.py @@ -35,6 +35,7 @@ """ +from __future__ import absolute_import from contextlib import contextmanager import datetime import os @@ -49,6 +50,7 @@ from exporter.main import run_tasks, archive_directory, upload_data, get_all_courses, _get_selected_tasks from exporter.config import setup, get_config_for_env, get_config_for_course from exporter.util import make_temp_directory, with_temp_directory, merge +import six log = logging.getLogger(__name__) @@ -150,7 +152,7 @@ def get_filename_safe_course_id(course_id, replacement_char='_'): """ try: course_key = CourseKey.from_string(course_id) - filename = unicode(replacement_char).join([course_key.org, course_key.course, course_key.run]) + filename = six.text_type(replacement_char).join([course_key.org, course_key.course, course_key.run]) except InvalidKeyError: # If the course_id doesn't parse, we will still return a value here. filename = course_id @@ -158,4 +160,4 @@ def get_filename_safe_course_id(course_id, replacement_char='_'): # The safest characters are A-Z, a-z, 0-9, , and . # We represent the first four with \w. # TODO: Once we support courses with unicode characters, we will need to revisit this. - return re.sub(r'[^\w\.\-]', unicode(replacement_char), filename) + return re.sub(r'[^\w\.\-]', six.text_type(replacement_char), filename) diff --git a/exporter/main.py b/exporter/main.py index f1a60f3..ad8d9f6 100755 --- a/exporter/main.py +++ b/exporter/main.py @@ -38,6 +38,7 @@ --django-pythonpath= The django python path """ +from __future__ import absolute_import from contextlib import contextmanager from copy import copy import datetime @@ -63,6 +64,7 @@ from exporter.util import make_temp_directory, with_temp_directory from exporter.util import filter_keys, memoize, execute_shell from exporter.util import logging_streams_on_failure +import six log = logging.getLogger(__name__) @@ -307,7 +309,7 @@ def get_all_courses(**kwargs): log.info('Retrieving all courses') # make a set of fixed arguments, so we can memoize - kwargs = {k: v for k, v in kwargs.iteritems() if k.startswith('django')} + kwargs = {k: v for k, v in six.iteritems(kwargs) if k.startswith('django')} kwargs['dry_run'] = False # always query for course names kwargs['limit'] = False # don't limit number of courses diff --git a/exporter/metrics.py b/exporter/metrics.py index 327bd27..56bc954 100644 --- a/exporter/metrics.py +++ b/exporter/metrics.py @@ -1,3 +1,4 @@ +from __future__ import absolute_import import calendar from contextlib import contextmanager from datetime import datetime diff --git a/exporter/mysql_query.py b/exporter/mysql_query.py index 60ca88b..57621ac 100644 --- a/exporter/mysql_query.py +++ b/exporter/mysql_query.py @@ -1,7 +1,9 @@ +from __future__ import absolute_import from contextlib import closing import json import csv import mysql.connector +import six MAX_FETCH_SIZE = 10000 @@ -59,4 +61,4 @@ def _write_results_to_tsv(self, cursor, output_file): def _normalize_value(self, value): if value is None: value='NULL' - return unicode(value).encode('utf-8').replace('\\', '\\\\').replace('\r', '\\r').replace('\t','\\t').replace('\n', '\\n') + return six.text_type(value).encode('utf-8').replace('\\', '\\\\').replace('\r', '\\r').replace('\t','\\t').replace('\n', '\\n') diff --git a/exporter/properties.py b/exporter/properties.py index d9c6c63..5907644 100755 --- a/exporter/properties.py +++ b/exporter/properties.py @@ -28,6 +28,8 @@ Can use wildcards. """ +from __future__ import absolute_import +from __future__ import print_function import os.path import shutil import sys @@ -55,7 +57,7 @@ def export_properties(config, directory, files=None, orgs=None, prefix=''): recreate_directory(directory) orgs = [o.lower() for o in orgs.split()] if orgs else ['*'] - print orgs + print(orgs) files_data = load_files(files) diff --git a/exporter/tasks.py b/exporter/tasks.py index 3cd5e6c..8dbe68d 100644 --- a/exporter/tasks.py +++ b/exporter/tasks.py @@ -1,5 +1,7 @@ # pylint: disable=missing-docstring +from __future__ import absolute_import +from __future__ import print_function import logging import os import subprocess @@ -11,10 +13,8 @@ from exporter.mysql_query import MysqlDumpQueryToTSV from exporter.util import NotSet, execute_shell - setup_logging() - log = logging.getLogger(__name__) MAX_TRIES_FOR_MARKER_FILE_CHECK = 5 @@ -84,6 +84,7 @@ def write_failed_file(cls, **kwargs): class OrgTask(FilenameMixin): """ Mixin class for organization level tasks.""" + @staticmethod def entity_name(kwargs): organization = _substitute_non_ascii_chars(kwargs['organization']) @@ -142,9 +143,10 @@ def run(cls, filename, dry_run, **kwargs): log.debug(query) if dry_run: - print 'SQL: {0}'.format(query) + print('SQL: {0}'.format(query)) else: - mysql_query = MysqlDumpQueryToTSV(kwargs.get('sql_host'), kwargs.get('sql_user'), kwargs.get('sql_password'), kwargs.get('sql_db'), filename) + mysql_query = MysqlDumpQueryToTSV(kwargs.get('sql_host'), kwargs.get('sql_user'), + kwargs.get('sql_password'), kwargs.get('sql_db'), filename) mysql_query.execute(query) @classmethod @@ -193,7 +195,7 @@ def run(cls, filename, dry_run, **kwargs): cmd = cmd.format(filename=filename, query=query, **kwargs) if dry_run: - print 'MONGO: {0}'.format(query) + print('MONGO: {0}'.format(query)) else: execute_shell(cmd, **kwargs) @@ -265,9 +267,9 @@ def run(cls, filename, dry_run, **kwargs): ) if dry_run: - print 'Copy S3 File: {0} to {1}'.format( + print('Copy S3 File: {0} to {1}'.format( s3_source_filename, - filename) + filename)) else: # First check to see that the export data was successfully generated # by looking for a marker file for that run. Return a more severe failure, @@ -368,6 +370,7 @@ class CourseEnrollmentTask(CourseTask, SQLTask): WHERE course_id='{course}' """ + class CourseGradesTask(CourseTask, SQLTask): NAME = 'grades_persistentcoursegrade' SQL = """ @@ -384,6 +387,7 @@ class CourseGradesTask(CourseTask, SQLTask): ORDER BY grades_persistentcoursegrade.user_id """ + class SubsectionGradesTask(CourseTask, SQLTask): NAME = 'grades_persistentsubsectiongrade' SQL = """ @@ -403,6 +407,7 @@ class SubsectionGradesTask(CourseTask, SQLTask): grades_persistentsubsectiongrade.first_attempted """ + class GeneratedCertificateTask(CourseTask, SQLTask): NAME = 'certificates_generatedcertificate' SQL = """ @@ -482,6 +487,7 @@ class StudentLanguageProficiencyTask(CourseTask, SQLTask): class CourseWikiTask(CourseTask): """ Mixin for Course Wiki related tasks """ + @classmethod def run(cls, filename, dry_run, **kwargs): course_key = CourseKey.from_string(kwargs['course']) @@ -603,6 +609,7 @@ class AssessmentAIClassifierTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}") """ + class AssessmentAIClassifierSetTask(ORA2CourseTask, SQLTask): NAME = 'assessment_aiclassifierset' SQL = """ @@ -610,6 +617,7 @@ class AssessmentAIClassifierSetTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}" """ + # Not used class AssessmentAIGradingWorkflowTask(ORA2CourseTask, SQLTask): NAME = 'assessment_aigradingworkflow' @@ -618,6 +626,7 @@ class AssessmentAIGradingWorkflowTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}" """ + class AssessmentAITrainingWorkflowTask(ORA2CourseTask, SQLTask): NAME = 'assessment_aitrainingworkflow' SQL = """ @@ -625,6 +634,7 @@ class AssessmentAITrainingWorkflowTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}" """ + class AssessmentAITrainingWorkflowTrainingExamplesTask(ORA2CourseTask, SQLTask): NAME = 'assessment_aitrainingworkflow_training_examples' SQL = """ @@ -633,6 +643,7 @@ class AssessmentAITrainingWorkflowTrainingExamplesTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}") """ + class AssessmentAssessmentTask(ORA2CourseTask, SQLTask): NAME = 'assessment_assessment' SQL = """ @@ -642,6 +653,7 @@ class AssessmentAssessmentTask(ORA2CourseTask, SQLTask): WHERE si.course_id="{course}" """ + class AssessmentAssessmentFeedbackTask(ORA2CourseTask, SQLTask): NAME = 'assessment_assessmentfeedback' SQL = """ @@ -654,6 +666,7 @@ class AssessmentAssessmentFeedbackTask(ORA2CourseTask, SQLTask): WHERE si.course_id="{course}" """ + class AssessmentAssessmentFeedbackAssessmentsTask(ORA2CourseTask, SQLTask): NAME = 'assessment_assessmentfeedback_assessments' SQL = """ @@ -664,6 +677,7 @@ class AssessmentAssessmentFeedbackAssessmentsTask(ORA2CourseTask, SQLTask): WHERE si.course_id="{course}" """ + class AssessmentAssessmentFeedbackOptionsTask(ORA2CourseTask, SQLTask): """ Note the 's' in FeedbackOptions (as compared to below) @@ -680,6 +694,7 @@ class AssessmentAssessmentFeedbackOptionsTask(ORA2CourseTask, SQLTask): WHERE si.course_id="{course}" """ + class AssessmentAssessmentFeedbackOptionTask(ORA2CourseTask, SQLTask): """ Note the lack of 's' in FeedbackOption (as compared to above) @@ -698,6 +713,7 @@ class AssessmentAssessmentFeedbackOptionTask(ORA2CourseTask, SQLTask): WHERE si.course_id="{course}" """ + class AssessmentAssessmentPartTask(ORA2CourseTask, SQLTask): NAME = 'assessment_assessmentpart' SQL = """ @@ -708,6 +724,7 @@ class AssessmentAssessmentPartTask(ORA2CourseTask, SQLTask): WHERE si.course_id="{course}" """ + class AssessmentCriterionTask(ORA2CourseTask, SQLTask): NAME = 'assessment_criterion' SQL = """ @@ -736,6 +753,7 @@ class AssessmentCriterionTask(ORA2CourseTask, SQLTask): WHERE acs.course_id="{course}") """ + class AssessmentCriterionOptionTask(ORA2CourseTask, SQLTask): NAME = 'assessment_criterionoption' SQL = """ @@ -766,6 +784,7 @@ class AssessmentCriterionOptionTask(ORA2CourseTask, SQLTask): WHERE acs.course_id="{course}")) """ + class AssessmentPeerWorkflowTask(ORA2CourseTask, SQLTask): NAME = 'assessment_peerworkflow' SQL = """ @@ -773,6 +792,7 @@ class AssessmentPeerWorkflowTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}" """ + class AssessmentPeerWorkflowItemTask(ORA2CourseTask, SQLTask): NAME = 'assessment_peerworkflowitem' SQL = """ @@ -781,6 +801,7 @@ class AssessmentPeerWorkflowItemTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}") """ + class AssessmentRubricTask(ORA2CourseTask, SQLTask): """ There can be rubrics for assessments, training examples, AI Grading Workflows, @@ -811,6 +832,7 @@ class AssessmentRubricTask(ORA2CourseTask, SQLTask): WHERE acs.course_id="{course}" """ + class AssessmentStudentTrainingWorkflow(ORA2CourseTask, SQLTask): NAME = 'assessment_studenttrainingworkflow' SQL = """ @@ -818,6 +840,7 @@ class AssessmentStudentTrainingWorkflow(ORA2CourseTask, SQLTask): WHERE course_id="{course}" """ + class AssessmentStudentTrainingWorkflowItemTask(ORA2CourseTask, SQLTask): NAME = 'assessment_studenttrainingworkflowitem' SQL = """ @@ -847,6 +870,7 @@ class AssessmentTrainingExampleTask(ORA2CourseTask, SQLTask): WHERE stw.course_id="{course}" """ + class AssessmentTrainingExampleOptionsSelectedTask(ORA2CourseTask, SQLTask): NAME = 'assessment_trainingexample_options_selected' SQL = """ @@ -866,6 +890,7 @@ class AssessmentTrainingExampleOptionsSelectedTask(ORA2CourseTask, SQLTask): WHERE stw.course_id="{course}") """ + class SubmissionsScoreTask(ORA2CourseTask, SQLTask): NAME = 'submissions_score' SQL = """ @@ -874,6 +899,7 @@ class SubmissionsScoreTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}") """ + class SubmissionsScoreSummaryTask(ORA2CourseTask, SQLTask): NAME = 'submissions_scoresummary' SQL = """ @@ -882,6 +908,7 @@ class SubmissionsScoreSummaryTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}") """ + class SubmissionsStudentItemTask(ORA2CourseTask, SQLTask): NAME = 'submissions_studentitem' SQL = """ @@ -889,6 +916,7 @@ class SubmissionsStudentItemTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}" """ + class SubmissionsSubmissionTask(ORA2CourseTask, SQLTask): NAME = 'submissions_submission' SQL = """ @@ -897,6 +925,7 @@ class SubmissionsSubmissionTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}") """ + class WorkflowAssessmentWorkflowTask(ORA2CourseTask, SQLTask): NAME = 'workflow_assessmentworkflow' SQL = """ @@ -904,6 +933,7 @@ class WorkflowAssessmentWorkflowTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}" """ + class WorkflowAssessmentWorkflowStepTask(ORA2CourseTask, SQLTask): NAME = 'workflow_assessmentworkflowstep' SQL = """ @@ -912,6 +942,7 @@ class WorkflowAssessmentWorkflowStepTask(ORA2CourseTask, SQLTask): WHERE course_id="{course}") """ + # End ORA2 Tables ================== class ForumsTask(CourseTask, MongoTask): @@ -987,7 +1018,7 @@ def run(cls, filename, dry_run, **kwargs): organizations = [kwargs['organization']] + kwargs.get('other_names', []) kwargs['comma_sep_courses'] = ','.join(kwargs['courses']) kwargs['all_organizations'] = ' '.join(organizations) - kwargs['max_tries'] = 3 # always retry this task a couple of times. + kwargs['max_tries'] = 3 # always retry this task a couple of times. return super(OrgEmailOptInTask, cls).run(filename, dry_run, **kwargs) diff --git a/exporter/tests/test_main.py b/exporter/tests/test_main.py index e8dff9b..4e4eeee 100644 --- a/exporter/tests/test_main.py +++ b/exporter/tests/test_main.py @@ -1,3 +1,7 @@ +from __future__ import absolute_import + +import operator + import mock from exporter import main, tasks @@ -14,8 +18,8 @@ def test_get_selected_tasks_no_options_org_tasks(): def test_get_selected_tasks_no_options_course_tasks(): assert sorted([ - task for task in tasks.DEFAULT_TASKS if issubclass(task, tasks.CourseTask) - ]) == sorted(main._get_selected_tasks(tasks.CourseTask, [], [])) + task for task in tasks.DEFAULT_TASKS if issubclass(task, tasks.CourseTask)], key=operator.attrgetter('NAME')) \ + == sorted(main._get_selected_tasks(tasks.CourseTask, [], []), key=operator.attrgetter('NAME')) def test_get_selected_tasks_specified_from_options(): @@ -23,9 +27,8 @@ def test_get_selected_tasks_specified_from_options(): def test_get_selected_tasks_excluded_tasks(): - assert sorted( - set(tasks.DEFAULT_TASKS) - set([tasks.OrgEmailOptInTask]) - ) == sorted(main._get_selected_tasks(tasks.Task, [], ['OrgEmailOptInTask'])) + assert sorted(set(tasks.DEFAULT_TASKS) - set([tasks.OrgEmailOptInTask]), key=operator.attrgetter('NAME')) \ + == sorted(main._get_selected_tasks(tasks.Task, [], ['OrgEmailOptInTask']), key=operator.attrgetter('NAME')) def test_run_tasks_happy_path(): diff --git a/exporter/tests/test_metrics.py b/exporter/tests/test_metrics.py index 7c34756..f2dde8d 100644 --- a/exporter/tests/test_metrics.py +++ b/exporter/tests/test_metrics.py @@ -1,3 +1,4 @@ +from __future__ import absolute_import from datetime import datetime import time diff --git a/exporter/tests/test_tasks.py b/exporter/tests/test_tasks.py index 0630930..bd52883 100644 --- a/exporter/tests/test_tasks.py +++ b/exporter/tests/test_tasks.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -* +from __future__ import absolute_import from copy import deepcopy from exporter import tasks diff --git a/exporter/util.py b/exporter/util.py index 824b5ad..5d03cd6 100644 --- a/exporter/util.py +++ b/exporter/util.py @@ -1,5 +1,6 @@ # pylint: disable=missing-docstring +from __future__ import absolute_import import atexit from contextlib import contextmanager import functools @@ -9,6 +10,7 @@ import subprocess import tempfile import time +import six log = logging.getLogger(__name__) @@ -20,8 +22,8 @@ def __str__(cls): raise ValueError("Value not set in child class") -class NotSet(object): - __metaclass__ = MetaNotSet +class NotSet(six.with_metaclass(MetaNotSet, object)): + pass # Dictionary utilities @@ -51,7 +53,7 @@ def filter_keys(mapping, keys): if keys: result = {k: {} for k in keys} result.update({k: v for k, v - in mapping.iteritems() + in six.iteritems(mapping) if k in keys}) else: result = mapping.copy() @@ -100,7 +102,7 @@ def with_temp_directory(*d_args, **d_kwargs): def wrap(func): @functools.wraps(func) def wrapped(*args): - if func.func_code.co_argcount - len(args) == 1: + if func.__code__.co_argcount - len(args) == 1: with make_temp_directory(*d_args, **d_kwargs) as temp_dir: args += (temp_dir,) return func(*args) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 37e24d4..0000000 --- a/requirements.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Application -awscli -docopt -edx-ccx-keys -edx-opaque-keys -graphitesend==0.10.0 # Apache -path.py -pbr -pip==1.5.6 # MIT // AN-4322 -pymongo -python-dateutil -python-gnupg==0.3.6 -pyyaml -psutil - -# Tests -coverage==4.3.4 -mock==2.0.0 -pytest==3.0.7 -pytest-cov==2.4.0 diff --git a/requirements/base.in b/requirements/base.in new file mode 100644 index 0000000..e819381 --- /dev/null +++ b/requirements/base.in @@ -0,0 +1,15 @@ +-c constraints.txt + +awscli +docopt +edx-ccx-keys +edx-opaque-keys +graphitesend +path.py +pbr +pip +pymongo +python-dateutil +python-gnupg +pyyaml +psutil diff --git a/requirements/base.txt b/requirements/base.txt new file mode 100644 index 0000000..5023485 --- /dev/null +++ b/requirements/base.txt @@ -0,0 +1,34 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# make upgrade +# +awscli==1.18.73 # via -r requirements/base.in +botocore==1.16.23 # via awscli, s3transfer +colorama==0.4.3 # via awscli +docopt==0.6.2 # via -r requirements/base.in +docutils==0.15.2 # via awscli, botocore +edx-ccx-keys==1.1.0 # via -r requirements/base.in +edx-opaque-keys==2.1.0 # via -r requirements/base.in, edx-ccx-keys +graphitesend==0.10.0 # via -r requirements/base.in +importlib-metadata==1.6.0 # via path +jmespath==0.10.0 # via botocore +path.py==12.4.0 # via -r requirements/base.in +path==13.1.0 # via path.py +pbr==5.4.5 # via -r requirements/base.in, stevedore +psutil==5.7.0 # via -r requirements/base.in +pyasn1==0.4.8 # via rsa +pymongo==3.10.1 # via -r requirements/base.in, edx-opaque-keys +python-dateutil==2.8.1 # via -r requirements/base.in, botocore +python-gnupg==0.4.6 # via -r requirements/base.in +pyyaml==5.3.1 # via -r requirements/base.in, awscli +rsa==3.4.2 # via awscli +s3transfer==0.3.3 # via awscli +six==1.15.0 # via edx-ccx-keys, edx-opaque-keys, python-dateutil, stevedore +stevedore==1.32.0 # via edx-opaque-keys +urllib3==1.25.9 # via botocore +zipp==1.2.0 # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# pip diff --git a/requirements/constraints.txt b/requirements/constraints.txt new file mode 100644 index 0000000..313b8f7 --- /dev/null +++ b/requirements/constraints.txt @@ -0,0 +1 @@ +# Version constraints for pip-installation. diff --git a/github_requirements.txt b/requirements/github.in similarity index 80% rename from github_requirements.txt rename to requirements/github.in index c1594ce..98ec1f8 100644 --- a/github_requirements.txt +++ b/requirements/github.in @@ -1 +1,3 @@ +-c constraints.txt + http://cdn.mysql.com/Downloads/Connector-Python/mysql-connector-python-1.2.2.zip diff --git a/requirements/github.txt b/requirements/github.txt new file mode 100644 index 0000000..f6ba802 --- /dev/null +++ b/requirements/github.txt @@ -0,0 +1,7 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# make upgrade +# +http://cdn.mysql.com/Downloads/Connector-Python/mysql-connector-python-1.2.2.zip # via -r requirements/github.in diff --git a/requirements/pip-tools.in b/requirements/pip-tools.in new file mode 100644 index 0000000..582243f --- /dev/null +++ b/requirements/pip-tools.in @@ -0,0 +1,5 @@ +# Allows us to generate version pins with `pip-compile`, and install +# them deterministically with `pip-sync`. +# `pip-compile` itself is used to generate pip-tools.txt. + +pip-tools \ No newline at end of file diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt new file mode 100644 index 0000000..d155f35 --- /dev/null +++ b/requirements/pip-tools.txt @@ -0,0 +1,12 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# make upgrade +# +click==7.1.2 # via pip-tools +pip-tools==5.2.0 # via -r requirements/pip-tools.in +six==1.15.0 # via pip-tools + +# The following packages are considered to be unsafe in a requirements file: +# pip diff --git a/requirements/test.in b/requirements/test.in new file mode 100644 index 0000000..90de7cc --- /dev/null +++ b/requirements/test.in @@ -0,0 +1,10 @@ +-c constraints.txt + +-r base.txt +-r github.txt + +coverage +mock +pytest +pytest-cov +setuptools diff --git a/requirements/test.txt b/requirements/test.txt new file mode 100644 index 0000000..35cbbd7 --- /dev/null +++ b/requirements/test.txt @@ -0,0 +1,47 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# make upgrade +# +attrs==19.3.0 # via pytest +awscli==1.18.73 # via -r requirements/base.txt +botocore==1.16.23 # via -r requirements/base.txt, awscli, s3transfer +colorama==0.4.3 # via -r requirements/base.txt, awscli +coverage==5.1 # via -r requirements/test.in, pytest-cov +docopt==0.6.2 # via -r requirements/base.txt +docutils==0.15.2 # via -r requirements/base.txt, awscli, botocore +edx-ccx-keys==1.1.0 # via -r requirements/base.txt +edx-opaque-keys==2.1.0 # via -r requirements/base.txt, edx-ccx-keys +graphitesend==0.10.0 # via -r requirements/base.txt +importlib-metadata==1.6.0 # via -r requirements/base.txt, path, pluggy, pytest +jmespath==0.10.0 # via -r requirements/base.txt, botocore +mock==3.0.5 # via -r requirements/test.in +more-itertools==8.3.0 # via pytest +http://cdn.mysql.com/Downloads/Connector-Python/mysql-connector-python-1.2.2.zip # via -r requirements/github.txt +packaging==20.4 # via pytest +path.py==12.4.0 # via -r requirements/base.txt +path==13.1.0 # via -r requirements/base.txt, path.py +pathlib2==2.3.5 # via pytest +pbr==5.4.5 # via -r requirements/base.txt, stevedore +pluggy==0.13.1 # via pytest +psutil==5.7.0 # via -r requirements/base.txt +py==1.8.1 # via pytest +pyasn1==0.4.8 # via -r requirements/base.txt, rsa +pymongo==3.10.1 # via -r requirements/base.txt, edx-opaque-keys +pyparsing==2.4.7 # via packaging +pytest-cov==2.9.0 # via -r requirements/test.in +pytest==5.4.3 # via -r requirements/test.in, pytest-cov +python-dateutil==2.8.1 # via -r requirements/base.txt, botocore +python-gnupg==0.4.6 # via -r requirements/base.txt +pyyaml==5.3.1 # via -r requirements/base.txt, awscli +rsa==3.4.2 # via -r requirements/base.txt, awscli +s3transfer==0.3.3 # via -r requirements/base.txt, awscli +six==1.15.0 # via -r requirements/base.txt, edx-ccx-keys, edx-opaque-keys, mock, packaging, pathlib2, python-dateutil, stevedore +stevedore==1.32.0 # via -r requirements/base.txt, edx-opaque-keys +urllib3==1.25.9 # via -r requirements/base.txt, botocore +wcwidth==0.2.3 # via pytest +zipp==1.2.0 # via -r requirements/base.txt, importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/requirements/tox.in b/requirements/tox.in new file mode 100644 index 0000000..ed6c885 --- /dev/null +++ b/requirements/tox.in @@ -0,0 +1,3 @@ +-c constraints.txt + +tox \ No newline at end of file diff --git a/requirements/tox.txt b/requirements/tox.txt new file mode 100644 index 0000000..efb0a48 --- /dev/null +++ b/requirements/tox.txt @@ -0,0 +1,20 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# make upgrade +# +appdirs==1.4.4 # via virtualenv +distlib==0.3.0 # via virtualenv +filelock==3.0.12 # via tox, virtualenv +importlib-metadata==1.6.0 # via importlib-resources, pluggy, tox, virtualenv +importlib-resources==1.5.0 # via virtualenv +packaging==20.4 # via tox +pluggy==0.13.1 # via tox +py==1.8.1 # via tox +pyparsing==2.4.7 # via packaging +six==1.15.0 # via packaging, tox, virtualenv +toml==0.10.1 # via tox +tox==3.15.1 # via -r requirements/tox.in +virtualenv==20.0.21 # via tox +zipp==1.2.0 # via importlib-metadata, importlib-resources diff --git a/test_requirements.txt b/test_requirements.txt deleted file mode 100644 index 47ab897..0000000 --- a/test_requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -setuptools<45 -tox diff --git a/tox.ini b/tox.ini index 90ce738..ee1af56 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,9 @@ [tox] -envlist = py27 +envlist = py27,py35 [testenv] deps = - -r{toxinidir}/requirements.txt - -r{toxinidir}/github_requirements.txt + -r{toxinidir}/requirements/test.txt commands = py.test {posargs}