Remove pkg_resources module (#4142)

This commit is contained in:
Bert Blommers 2021-08-05 17:59:25 +01:00 committed by GitHub
parent da09cfc39c
commit 76094f012b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 52 additions and 61 deletions

View File

@ -1,11 +1,9 @@
import json
import re import re
import time import time
import random import random
import string import string
from datetime import datetime from datetime import datetime
import pkg_resources
from boto3 import Session from boto3 import Session
@ -49,6 +47,7 @@ from moto.config.exceptions import (
from moto.core import BaseBackend, BaseModel from moto.core import BaseBackend, BaseModel
from moto.s3.config import s3_account_public_access_block_query, s3_config_query from moto.s3.config import s3_account_public_access_block_query, s3_config_query
from moto.core import ACCOUNT_ID as DEFAULT_ACCOUNT_ID from moto.core import ACCOUNT_ID as DEFAULT_ACCOUNT_ID
from moto.core.responses import AWSServiceSpec
from moto.iam.config import role_config_query, policy_config_query from moto.iam.config import role_config_query, policy_config_query
@ -419,15 +418,13 @@ class ConfigBackend(BaseBackend):
self.config_aggregators = {} self.config_aggregators = {}
self.aggregation_authorizations = {} self.aggregation_authorizations = {}
self.organization_conformance_packs = {} self.organization_conformance_packs = {}
self.config_schema = None
@staticmethod def _validate_resource_types(self, resource_list):
def _validate_resource_types(resource_list): if not self.config_schema:
# Load the service file: self.config_schema = AWSServiceSpec(
resource_package = "botocore" path="data/config/2014-11-12/service-2.json"
resource_path = "/".join(("data", "config", "2014-11-12", "service-2.json")) )
config_schema = json.loads(
pkg_resources.resource_string(resource_package, resource_path)
)
# Verify that each entry exists in the supported list: # Verify that each entry exists in the supported list:
bad_list = [] bad_list = []
@ -435,31 +432,28 @@ class ConfigBackend(BaseBackend):
# For PY2: # For PY2:
r_str = str(resource) r_str = str(resource)
if r_str not in config_schema["shapes"]["ResourceType"]["enum"]: if r_str not in self.config_schema.shapes["ResourceType"]["enum"]:
bad_list.append(r_str) bad_list.append(r_str)
if bad_list: if bad_list:
raise InvalidResourceTypeException( raise InvalidResourceTypeException(
bad_list, config_schema["shapes"]["ResourceType"]["enum"] bad_list, self.config_schema.shapes["ResourceType"]["enum"]
) )
@staticmethod def _validate_delivery_snapshot_properties(self, properties):
def _validate_delivery_snapshot_properties(properties): if not self.config_schema:
# Load the service file: self.config_schema = AWSServiceSpec(
resource_package = "botocore" path="data/config/2014-11-12/service-2.json"
resource_path = "/".join(("data", "config", "2014-11-12", "service-2.json")) )
conifg_schema = json.loads(
pkg_resources.resource_string(resource_package, resource_path)
)
# Verify that the deliveryFrequency is set to an acceptable value: # Verify that the deliveryFrequency is set to an acceptable value:
if ( if (
properties.get("deliveryFrequency", None) properties.get("deliveryFrequency", None)
not in conifg_schema["shapes"]["MaximumExecutionFrequency"]["enum"] not in self.config_schema.shapes["MaximumExecutionFrequency"]["enum"]
): ):
raise InvalidDeliveryFrequency( raise InvalidDeliveryFrequency(
properties.get("deliveryFrequency", None), properties.get("deliveryFrequency", None),
conifg_schema["shapes"]["MaximumExecutionFrequency"]["enum"], self.config_schema.shapes["MaximumExecutionFrequency"]["enum"],
) )
def put_configuration_aggregator(self, config_aggregator, region): def put_configuration_aggregator(self, config_aggregator, region):

View File

@ -5,17 +5,18 @@ from __future__ import absolute_import
import functools import functools
import inspect import inspect
import os import os
import pkg_resources
import re import re
import types import types
from abc import abstractmethod from abc import abstractmethod
from io import BytesIO from io import BytesIO
from collections import defaultdict from collections import defaultdict
from botocore.config import Config from botocore.config import Config
from botocore.handlers import BUILTIN_HANDLERS from botocore.handlers import BUILTIN_HANDLERS
from botocore.awsrequest import AWSResponse from botocore.awsrequest import AWSResponse
from distutils.version import LooseVersion from distutils.version import LooseVersion
from http.client import responses as http_responses from http.client import responses as http_responses
from importlib_metadata import version
from urllib.parse import urlparse from urllib.parse import urlparse
from werkzeug.wrappers import Request from werkzeug.wrappers import Request
@ -30,7 +31,6 @@ from .utils import (
) )
ACCOUNT_ID = os.environ.get("MOTO_ACCOUNT_ID", "123456789012") ACCOUNT_ID = os.environ.get("MOTO_ACCOUNT_ID", "123456789012")
RESPONSES_VERSION = pkg_resources.get_distribution("responses").version
class BaseMockAWS: class BaseMockAWS:
@ -306,6 +306,7 @@ def _find_first_match(self, request):
# - First request matches on the appropriate S3 URL # - First request matches on the appropriate S3 URL
# - Same request, executed again, will be matched on the subsequent match, which happens to be the catch-all, not-yet-implemented, callback # - Same request, executed again, will be matched on the subsequent match, which happens to be the catch-all, not-yet-implemented, callback
# Fix: Always return the first match # Fix: Always return the first match
RESPONSES_VERSION = version("responses")
if LooseVersion(RESPONSES_VERSION) < LooseVersion("0.12.1"): if LooseVersion(RESPONSES_VERSION) < LooseVersion("0.12.1"):
responses_mock._find_match = types.MethodType( responses_mock._find_match = types.MethodType(
_find_first_match_legacy, responses_mock _find_first_match_legacy, responses_mock

View File

@ -6,7 +6,6 @@ import datetime
import json import json
import logging import logging
import re import re
import io
import requests import requests
import pytz import pytz
@ -23,6 +22,7 @@ from werkzeug.exceptions import HTTPException
import boto3 import boto3
from collections import OrderedDict from collections import OrderedDict
from moto.core.utils import camelcase_to_underscores, method_names_from_class from moto.core.utils import camelcase_to_underscores, method_names_from_class
from moto.utilities.utils import load_resource
from moto import settings from moto import settings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -903,12 +903,8 @@ class AWSServiceSpec(object):
""" """
def __init__(self, path): def __init__(self, path):
# Importing pkg_resources takes ~60ms; keep it local spec = load_resource("botocore", path)
from pkg_resources import resource_filename # noqa
self.path = resource_filename("botocore", path)
with io.open(self.path, "r", encoding="utf-8") as f:
spec = json.load(f)
self.metadata = spec["metadata"] self.metadata = spec["metadata"]
self.operations = spec["operations"] self.operations = spec["operations"]
self.shapes = spec["shapes"] self.shapes = spec["shapes"]

View File

@ -1,5 +1,4 @@
from moto.utilities.utils import load_resource from moto.utilities.utils import load_resource
from pkg_resources import resource_filename
class ReservedKeywords(list): class ReservedKeywords(list):
@ -23,6 +22,6 @@ class ReservedKeywords(list):
Get a list of reserved keywords of DynamoDB Get a list of reserved keywords of DynamoDB
""" """
reserved_keywords = load_resource( reserved_keywords = load_resource(
resource_filename(__name__, "reserved_keywords.txt"), as_json=False __name__, "reserved_keywords.txt", as_json=False
) )
return reserved_keywords.split() return reserved_keywords.split()

View File

@ -5,11 +5,11 @@ import itertools
import ipaddress import ipaddress
import json import json
import os import os
import pathlib
import re import re
import warnings import warnings
from boto3 import Session from boto3 import Session
from pkg_resources import resource_filename
from collections import defaultdict from collections import defaultdict
import weakref import weakref
@ -173,30 +173,25 @@ from .utils import (
describe_tag_filter, describe_tag_filter,
) )
INSTANCE_TYPES = load_resource(__name__, "resources/instance_types.json")
INSTANCE_TYPES = load_resource( root = pathlib.Path(__file__).parent
resource_filename(__name__, "resources/instance_types.json")
)
offerings_path = "resources/instance_type_offerings" offerings_path = "resources/instance_type_offerings"
INSTANCE_TYPE_OFFERINGS = {} INSTANCE_TYPE_OFFERINGS = {}
for location_type in listdir(resource_filename(__name__, offerings_path)): for location_type in listdir(root / offerings_path):
INSTANCE_TYPE_OFFERINGS[location_type] = {} INSTANCE_TYPE_OFFERINGS[location_type] = {}
for region in listdir( for region in listdir(root / offerings_path / location_type):
resource_filename(__name__, offerings_path + "/" + location_type) full_path = offerings_path + "/" + location_type + "/" + region
):
full_path = resource_filename(
__name__, offerings_path + "/" + location_type + "/" + region
)
INSTANCE_TYPE_OFFERINGS[location_type][ INSTANCE_TYPE_OFFERINGS[location_type][
region.replace(".json", "") region.replace(".json", "")
] = load_resource(full_path) ] = load_resource(__name__, full_path)
AMIS = load_resource( if "MOTO_AMIS_PATH" in os.environ:
os.environ.get("MOTO_AMIS_PATH") with open(os.environ.get("MOTO_AMIS_PATH"), "r", encoding="utf-8") as f:
or resource_filename(__name__, "resources/amis.json"), AMIS = json.load(f)
) else:
AMIS = load_resource(__name__, "resources/amis.json")
OWNER_ID = ACCOUNT_ID OWNER_ID = ACCOUNT_ID

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from boto3 import Session from boto3 import Session
from pkg_resources import resource_filename
from moto.core import BaseBackend from moto.core import BaseBackend
from moto.utilities.utils import load_resource from moto.utilities.utils import load_resource
import datetime import datetime
@ -8,7 +7,7 @@ import random
checks_json = "resources/describe_trusted_advisor_checks.json" checks_json = "resources/describe_trusted_advisor_checks.json"
ADVISOR_CHECKS = load_resource(resource_filename(__name__, checks_json)) ADVISOR_CHECKS = load_resource(__name__, checks_json)
class SupportCase(object): class SupportCase(object):

View File

@ -1,6 +1,7 @@
import json import json
import random import random
import string import string
import pkgutil
def str2bool(v): def str2bool(v):
@ -18,15 +19,14 @@ def random_string(length=None):
return random_str return random_str
def load_resource(filename, as_json=True): def load_resource(package, resource, as_json=True):
""" """
Open a file, and return the contents as JSON. Open a file, and return the contents as JSON.
Usage: Usage:
from pkg_resources import resource_filename load_resource(__name__, "resources/file.json")
load_resource(resource_filename(__name__, "resources/file.json"))
""" """
with open(filename, "r", encoding="utf-8") as f: resource = pkgutil.get_data(package, resource)
return json.load(f) if as_json else f.read() return json.loads(resource) if as_json else resource.decode("utf-8")
def merge_multiple_dicts(*args): def merge_multiple_dicts(*args):

View File

@ -52,6 +52,9 @@ test_service() {
pip install -r requirements-tests.txt > /dev/null pip install -r requirements-tests.txt > /dev/null
pip install .[$service] > /dev/null 2>&1 pip install .[$service] > /dev/null 2>&1
pip install boto > /dev/null 2>&1 pip install boto > /dev/null 2>&1
if [[ $service != "xray" ]]; then
pip uninstall setuptools pkg_resources -y > /dev/null 2>&1
fi
# Restart venv - ensure these deps are loaded # Restart venv - ensure these deps are loaded
deactivate deactivate
source ${venv_path}/bin/activate > /dev/null source ${venv_path}/bin/activate > /dev/null

View File

@ -39,6 +39,7 @@ install_requires = [
"MarkupSafe!=2.0.0a1", # This is a Jinja2 dependency, 2.0.0a1 currently seems broken "MarkupSafe!=2.0.0a1", # This is a Jinja2 dependency, 2.0.0a1 currently seems broken
"Jinja2>=2.10.1", "Jinja2>=2.10.1",
"more-itertools", "more-itertools",
"importlib_metadata"
] ]
_dep_PyYAML = "PyYAML>=5.1" _dep_PyYAML = "PyYAML>=5.1"
@ -52,6 +53,7 @@ _dep_aws_xray_sdk = "aws-xray-sdk!=0.96,>=0.93"
_dep_idna = "idna<3,>=2.5" _dep_idna = "idna<3,>=2.5"
_dep_cfn_lint = "cfn-lint>=0.4.0" _dep_cfn_lint = "cfn-lint>=0.4.0"
_dep_sshpubkeys = "sshpubkeys>=3.1.0" _dep_sshpubkeys = "sshpubkeys>=3.1.0"
_setuptools = "setuptools"
all_extra_deps = [ all_extra_deps = [
_dep_PyYAML, _dep_PyYAML,
@ -63,6 +65,7 @@ all_extra_deps = [
_dep_idna, _dep_idna,
_dep_cfn_lint, _dep_cfn_lint,
_dep_sshpubkeys, _dep_sshpubkeys,
_setuptools,
] ]
all_server_deps = all_extra_deps + ["flask", "flask-cors"] all_server_deps = all_extra_deps + ["flask", "flask-cors"]
@ -82,7 +85,9 @@ extras_per_service = {
"sns": [], "sns": [],
"sqs": [], "sqs": [],
"ssm": [_dep_PyYAML], "ssm": [_dep_PyYAML],
"xray": [_dep_aws_xray_sdk], # XRay module uses pkg_resources, but doesn't have an explicit dependency listed
# This should be fixed in the next version: https://github.com/aws/aws-xray-sdk-python/issues/305
"xray": [_dep_aws_xray_sdk, _setuptools],
} }
# When a Table has a Stream, we'll always need to import AWSLambda to search for a corresponding function to send the table data to # When a Table has a Stream, we'll always need to import AWSLambda to search for a corresponding function to send the table data to
extras_per_service["dynamodb2"] = extras_per_service["awslambda"] extras_per_service["dynamodb2"] = extras_per_service["awslambda"]

View File

@ -5,19 +5,18 @@ import botocore.exceptions
import sure # noqa import sure # noqa
import datetime import datetime
import json import json
import pkg_resources
import yaml import yaml
import hashlib import hashlib
import copy import copy
import pkgutil
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from moto import mock_ssm from moto import mock_ssm
def _get_yaml_template(): def _get_yaml_template():
template_path = "/".join(["test_ssm", "test_templates", "good.yaml"]) return pkgutil.get_data(__name__, "test_templates/good.yaml")
resource_path = pkg_resources.resource_string("tests", template_path)
return resource_path
def _validate_document_description( def _validate_document_description(