from__future__importannotationsimportloggingimportosimporttypingastfrom.env_varsimportget_environment_namelog=logging.getLogger(__name__)# the format string for a service URL pulled out of the environment# these are handled with uppercased service names, e.g.# `GLOBUS_SDK_SERVICE_URL_SEARCH=...`_SERVICE_URL_VAR_FORMAT="GLOBUS_SDK_SERVICE_URL_{}"classEnvConfig:envname:strdomain:strno_dotapi:list[str]=["app","auth"]automate_services:list[str]=["actions","flows","timer"]# this same dict is inherited (and therefore shared!) by all subclasses_registry:dict[str,type[EnvConfig]]={}# this is an easier hook to use than metaclass definition -- register every subclass# in this dict automatically## as a result, anyone can define## class BetaEnv(EnvConfig):# domain = "beta.foo.bar.example.com"# envname = "beta"## and retrieve it with get_config_by_name("beta")def__init_subclass__(cls,**kwargs:t.Any):super().__init_subclass__(**kwargs)cls._registry[cls.envname]=cls@classmethoddefget_service_url(cls,service:str)->str:# you can override any name with a config attributeservice_url_attr=f"{service}_url"ifhasattr(cls,service_url_attr):returnt.cast(str,getattr(cls,service_url_attr))# the typical pattern for a service hostname is X.api.Y# X=transfer, Y=preview.globus.org => transfer.api.preview.globus.org# check `no_dotapi` for services which don't have `.api` in their namesifserviceincls.no_dotapi:returnf"https://{service}.{cls.domain}/"ifserviceincls.automate_services:returnf"https://{cls.envname}.{service}.automate.globus.org/"returnf"https://{service}.api.{cls.domain}/"@classmethoddefget_by_name(cls,env:str)->type[EnvConfig]|None:returncls._registry.get(env)
[docs]defget_service_url(service:str,environment:str|None=None)->str:""" Return the base URL for the given service in this environment. For example: >>> from globus_sdk.config import get_service_url >>> get_service_url("auth", environment="preview") 'https://auth.preview.globus.org/' >>> get_service_url("search", environment="production") 'https://search.api.globus.org/' :param service: The short name of the service to get the URL for :param environment: The name of the environment to use. If unspecified, this will use the ``GLOBUS_SDK_ENVIRONMENT`` environment variable. """log.debug(f'Service URL Lookup for "{service}" under env "{environment}"')environment=environmentorget_environment_name()# check for an environment variable of the form# GLOBUS_SDK_SERVICE_URL_*# and use it ahead of any env config if setvarname=_SERVICE_URL_VAR_FORMAT.format(service.upper())from_env=os.getenv(varname)iffrom_env:log.debug(f"Got URL from env var, {varname}={from_env}")returnfrom_envconf=EnvConfig.get_by_name(environment)ifnotconf:raiseValueError(f'Unrecognized environment "{environment}"')url=conf.get_service_url(service)log.debug(f'Service URL Lookup Result: "{service}" is at "{url}"')returnurl
[docs]defget_webapp_url(environment:str|None=None)->str:""" Return the URL to access the Globus web app in the given environment. For example: >>> get_webapp_url("preview") 'https://app.preview.globus.org/' :param environment: The name of the environment to use. If unspecified, this will use the ``GLOBUS_SDK_ENVIRONMENT`` environment variable. """environment=environmentorget_environment_name()returnget_service_url("app",environment=environment)
## public environments#classProductionEnvConfig(EnvConfig):envname="production"domain="globus.org"nexus_url="https://nexus.api.globusonline.org/"timer_url="https://timer.automate.globus.org/"flows_url="https://flows.automate.globus.org/"actions_url="https://actions.automate.globus.org/"classPreviewEnvConfig(EnvConfig):envname="preview"domain="preview.globus.org"## environments for internal use only#forenvnamein["sandbox","integration","test","staging"]:# use `type()` rather than the `class` syntax to control classnamestype(f"{envname.title()}EnvConfig",(EnvConfig,),{"envname":envname,"domain":f"{envname}.globuscs.info",},)