Skip to content

Commit

Permalink
move contextlib2 into python_utils (oppia#12773)
Browse files Browse the repository at this point in the history
  • Loading branch information
brianrodri authored May 21, 2021
1 parent ccced17 commit f3c7bc2
Show file tree
Hide file tree
Showing 15 changed files with 103 additions and 75 deletions.
43 changes: 23 additions & 20 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,37 @@ indent-string=' '

allowed-comment-prefixes=int,str,float,bool,v
forbidden-imports=
core.storage:core.domain,
core.controllers:core.platform|core.storage,
core.domain:core.controllers,
core.controllers:core.platform|core.storage
core.storage:core.domain

disallowed-functions-and-replacements-str=
now=>datetime.datetime.utcnow,
assertEquals=>self.assertEqual,
StringIO=>python_utils.string_io,
urlparse.urlsplit=>python_utils.url_split,
urlparse.urlparse=>python_utils.url_parse,
urlparse.urlunsplit=>python_utils.url_unsplit,
urlparse.parse_qs=>python_utils.parse_query_string,
urlparse.urljoin=>python_utils.url_join,
urllib.unquote=>python_utils.urllib_unquote,
urllib.urlparse.unquote=>python_utils.urllib_unquote,
next=>python_utils.NEXT,
range=>python_utils.RANGE,
round=>python_utils.ROUND,
str=>python_utils.convert_to_bytes or python_utils.UNICODE,
zip=>python_utils.ZIP,
basestring=>python_utils.BASESTRING,
contextlib2.ExitStack=>python_utils.ExitStack,
contextlib2.nullcontext=>python_utils.nullcontext,
contextlib2.redirect_stdout=>python_utils.redirect_stdout,
input=>python_utils.INPUT,
iteritems=>items,
itervalues=>values,
iterkeys=>keys,
print=>python_utils.PRINT,
itervalues=>values,
map=>python_utils.MAP,
next=>python_utils.NEXT,
now=>datetime.datetime.utcnow,
open=>python_utils.open_file,
input=>python_utils.INPUT,
map=>python_utils.MAP
print=>python_utils.PRINT,
range=>python_utils.RANGE,
round=>python_utils.ROUND,
str=>python_utils.convert_to_bytes or python_utils.UNICODE,
StringIO=>python_utils.string_io,
urllib.unquote=>python_utils.urllib_unquote,
urllib.urlparse.unquote=>python_utils.urllib_unquote,
urlparse.parse_qs=>python_utils.parse_query_string,
urlparse.urljoin=>python_utils.url_join,
urlparse.urlparse=>python_utils.url_parse,
urlparse.urlsplit=>python_utils.url_split,
urlparse.urlunsplit=>python_utils.url_unsplit,
zip=>python_utils.ZIP

disallowed-functions-and-replacements-regex=
\.put_async\(=>put,
Expand Down
7 changes: 3 additions & 4 deletions core/controllers/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
import python_utils
import utils

import contextlib2
from mapreduce import main as mapreduce_main
import webapp2
import webtest
Expand Down Expand Up @@ -555,7 +554,7 @@ def test_splash_redirect(self):
self.assertEqual('http://localhost/', response.headers['location'])

def test_unauthorized_user_exception_raised_when_session_is_stale(self):
with contextlib2.ExitStack() as exit_stack:
with python_utils.ExitStack() as exit_stack:
call_counter = exit_stack.enter_context(self.swap_with_call_counter(
auth_services, 'destroy_auth_session'))
logs = exit_stack.enter_context(
Expand All @@ -572,7 +571,7 @@ def test_unauthorized_user_exception_raised_when_session_is_stale(self):
'http://localhost/login?return_url=http%3A%2F%2Flocalhost%2F')

def test_unauthorized_user_exception_raised_when_session_is_invalid(self):
with contextlib2.ExitStack() as exit_stack:
with python_utils.ExitStack() as exit_stack:
call_counter = exit_stack.enter_context(self.swap_with_call_counter(
auth_services, 'destroy_auth_session'))
logs = exit_stack.enter_context(
Expand All @@ -598,7 +597,7 @@ class MaintenanceModeTests(test_utils.GenericTestBase):

def setUp(self):
super(MaintenanceModeTests, self).setUp()
with contextlib2.ExitStack() as context_stack:
with python_utils.ExitStack() as context_stack:
context_stack.enter_context(
self.swap(feconf, 'ENABLE_MAINTENANCE_MODE', True))
self.context_stack = context_stack.pop_all()
Expand Down
5 changes: 2 additions & 3 deletions core/domain/auth_jobs_one_off_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
from core.platform.auth import firebase_auth_services_test
from core.tests import test_utils
import feconf

import contextlib2
import python_utils

auth_models, user_models = (
models.Registry.import_models([models.NAMES.auth, models.NAMES.user]))
Expand All @@ -48,7 +47,7 @@ class SyncFirebaseAccountsOneOffJobTests(test_utils.AppEngineTestBase):

def setUp(self):
super(SyncFirebaseAccountsOneOffJobTests, self).setUp()
self.exit_stack = contextlib2.ExitStack()
self.exit_stack = python_utils.ExitStack()
self.firebase_sdk_stub = (
firebase_auth_services_test.FirebaseAdminSdkStub())

Expand Down
5 changes: 2 additions & 3 deletions core/domain/state_domain_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@
from core.domain import translatable_object_registry
from core.tests import test_utils
import feconf
import python_utils
import schema_utils
import utils

import contextlib2


class StateDomainUnitTests(test_utils.GenericTestBase):
"""Test methods operating on states."""
Expand Down Expand Up @@ -3842,7 +3841,7 @@ def test_validate_duplicate_content_id_with_solution(self):
def test_cannot_convert_state_dict_to_yaml_with_invalid_state_dict(self):
exploration = self.save_new_valid_exploration('exp_id', 'owner_id')

with contextlib2.ExitStack() as stack:
with python_utils.ExitStack() as stack:
captured_logs = stack.enter_context(
self.capture_logging(min_level=logging.ERROR))
stack.enter_context(
Expand Down
3 changes: 1 addition & 2 deletions core/jobs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import feconf
import python_utils

import contextlib2
from mapreduce import input_readers

(base_models, exp_models, stats_models, job_models) = (
Expand Down Expand Up @@ -232,7 +231,7 @@ def test_failing_jobs(self):
job_id = MockJobManagerOne.create_new()
store_map_reduce_results = jobs.StoreMapReduceResults()

with contextlib2.ExitStack() as stack:
with python_utils.ExitStack() as stack:
captured_logs = stack.enter_context(
self.capture_logging(min_level=logging.ERROR))
stack.enter_context(input_reader_swap)
Expand Down
3 changes: 1 addition & 2 deletions core/platform/auth/firebase_auth_services_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import python_utils
import utils

import contextlib2
import firebase_admin
from firebase_admin import auth as firebase_auth
from firebase_admin import exceptions as firebase_exceptions
Expand Down Expand Up @@ -115,7 +114,7 @@ def install(self, test):

self._test = test

with contextlib2.ExitStack() as swap_stack:
with python_utils.ExitStack() as swap_stack:
for name in self._IMPLEMENTED_SDK_FUNCTION_NAMES:
swap_stack.enter_context(
test.swap(firebase_auth, name, getattr(self, name)))
Expand Down
5 changes: 2 additions & 3 deletions core/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
import schema_utils
import utils

import contextlib2
import elasticsearch
from google.appengine.ext import deferred
from google.appengine.ext import testbed
Expand Down Expand Up @@ -532,7 +531,7 @@ def install_stub(cls, test):
Returns:
callable. A function that will uninstall the stub when called.
"""
with contextlib2.ExitStack() as stack:
with python_utils.ExitStack() as stack:
stub = cls()

stack.enter_context(test.swap(
Expand Down Expand Up @@ -1844,7 +1843,7 @@ def run(self, result=None):
es_stub = ElasticSearchStub()
es_stub.reset()

with contextlib2.ExitStack() as stack:
with python_utils.ExitStack() as stack:
stack.callback(AuthServicesStub.install_stub(self))
stack.enter_context(self.swap(
elastic_search_services.ES.indices, 'create',
Expand Down
6 changes: 3 additions & 3 deletions jobs/job_test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from __future__ import unicode_literals # pylint: disable=import-only-modules

import ast
import contextlib
import datetime
import re

Expand All @@ -32,7 +33,6 @@
from apache_beam import runners
from apache_beam.testing import test_pipeline
from apache_beam.testing import util as beam_testing_util
import contextlib2


class PipelinedTestBase(test_utils.TestBase):
Expand All @@ -52,7 +52,7 @@ def __init__(self, *args, **kwargs):

def setUp(self):
super(PipelinedTestBase, self).setUp()
with contextlib2.ExitStack() as stack:
with python_utils.ExitStack() as stack:
stack.enter_context(decorate_beam_errors())
stack.enter_context(self.pipeline)
self._close_stack = stack.pop_all().close
Expand Down Expand Up @@ -187,7 +187,7 @@ def assert_job_output_is_empty(self):
self.assert_pcoll_empty(self.run_job())


@contextlib2.contextmanager
@contextlib.contextmanager
def decorate_beam_errors():
"""Context manager to improve the readability of beam_testing_util errors.
Expand Down
51 changes: 51 additions & 0 deletions python_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,57 @@
ZIP = builtins.zip


def redirect_stdout(new_target):
"""Returns redirect_stdout from contextlib2 if run under Python 2 and from
contextlib if run under Python 3.
Args:
new_target: FileLike. The file-like object all messages printed to
stdout will be redirected to.
Returns:
contextlib.redirect_stdout or contextlib2.redirect_stdout. The
redirect_stdout object.
"""
try:
from contextlib import redirect_stdout as impl # pylint: disable=import-only-modules
except ImportError:
from contextlib2 import redirect_stdout as impl # pylint: disable=import-only-modules
return impl(new_target)


def nullcontext(enter_result=None):
"""Returns nullcontext from contextlib2 if run under Python 2 and from
contextlib if run under Python 3.
Args:
enter_result: *. The object returned by the nullcontext when entered.
Returns:
contextlib.nullcontext or contextlib2.nullcontext. The nullcontext
object.
"""
try:
from contextlib import nullcontext as impl # pylint: disable=import-only-modules
except ImportError:
from contextlib2 import nullcontext as impl # pylint: disable=import-only-modules
return impl(enter_result=enter_result)


def ExitStack(): # pylint: disable=invalid-name
"""Returns ExitStack from contextlib2 if run under Python 2 and from
contextlib if run under Python 3.
Returns:
contextlib.ExitStack or contextlib2.ExitStack. The ExitStack object.
"""
try:
from contextlib import ExitStack as impl # pylint: disable=import-only-modules
except ImportError:
from contextlib2 import ExitStack as impl # pylint: disable=import-only-modules
return impl()


def string_io(buffer_value=b''):
"""Returns StringIO from StringIO module if run under Python 2 and from io
module if run under Python 3.
Expand Down
5 changes: 1 addition & 4 deletions scripts/run_e2e_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,12 @@ def build_js_files(dev_mode, deparallelize_terser=False, source_maps=False):

def run_tests(args):
"""Run the scripts to start end-to-end tests."""
# TODO(#11549): Move this to top of the file.
import contextlib2

if is_oppia_server_already_running():
sys.exit(1)

install_third_party_libraries(args.skip_install)

with contextlib2.ExitStack() as stack:
with python_utils.ExitStack() as stack:
dev_mode = not args.prod_env

if args.skip_build:
Expand Down
9 changes: 4 additions & 5 deletions scripts/run_e2e_tests_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import time

from core.tests import test_utils
import python_utils
from scripts import build
from scripts import common
from scripts import flake_checker
Expand All @@ -32,8 +33,6 @@
from scripts import scripts_test_utils
from scripts import servers

import contextlib2

CHROME_DRIVER_VERSION = '77.0.3865.40'


Expand All @@ -44,7 +43,7 @@ def mock_managed_process(*unused_args, **unused_kwargs):
Context manager. A context manager that always yields a mock
process.
"""
return contextlib2.nullcontext(
return python_utils.nullcontext(
enter_result=scripts_test_utils.PopenStub(alive=False))


Expand All @@ -53,7 +52,7 @@ class RunE2ETestsTests(test_utils.GenericTestBase):

def setUp(self):
super(RunE2ETestsTests, self).setUp()
self.exit_stack = contextlib2.ExitStack()
self.exit_stack = python_utils.ExitStack()

def tearDown(self):
try:
Expand Down Expand Up @@ -277,7 +276,7 @@ def test_start_tests_when_no_other_instance_running(self):

def test_work_with_non_ascii_chars(self):
def mock_managed_protractor_server(**unused_kwargs): # pylint: disable=unused-argument
return contextlib2.nullcontext(
return python_utils.nullcontext(
enter_result=scripts_test_utils.PopenStub(
stdout='sample\n\noutput\n', alive=False))

Expand Down
5 changes: 1 addition & 4 deletions scripts/run_lighthouse_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ def run_lighthouse_checks(lighthouse_mode):

def main(args=None):
"""Runs lighthouse checks and deletes reports."""
# TODO(#11549): Move this to top of the file.
import contextlib2

parsed_args = _PARSER.parse_args(args=args)

if parsed_args.mode == LIGHTHOUSE_MODE_ACCESSIBILITY:
Expand All @@ -161,7 +158,7 @@ def main(args=None):
build.main(args=[])
run_webpack_compilation()

with contextlib2.ExitStack() as stack:
with python_utils.ExitStack() as stack:
stack.enter_context(common.inplace_replace_file_context(
common.CONSTANTS_FILE_PATH,
'"ENABLE_ACCOUNT_DELETION": .*',
Expand Down
Loading

0 comments on commit f3c7bc2

Please sign in to comment.