Skip to content

Commit b1a2da3

Browse files
authored
Merge pull request #6653 from readthedocs/humitos/default-python-version
Default python version per Docker image
2 parents cd2bee3 + a9e602f commit b1a2da3

File tree

3 files changed

+99
-15
lines changed

3 files changed

+99
-15
lines changed

readthedocs/config/config.py

+35-9
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,11 @@
3030
validate_bool,
3131
validate_choice,
3232
validate_dict,
33-
validate_path,
3433
validate_list,
34+
validate_path,
3535
validate_string,
3636
)
3737

38-
3938
__all__ = (
4039
'ALL',
4140
'load',
@@ -83,7 +82,7 @@ class ConfigFileNotFound(ConfigError):
8382

8483
def __init__(self, directory):
8584
super().__init__(
86-
f"Configuration file not found in: {directory}",
85+
f'Configuration file not found in: {directory}',
8786
CONFIG_FILE_REQUIRED,
8887
)
8988

@@ -255,11 +254,10 @@ def python_interpreter(self):
255254
def python_full_version(self):
256255
ver = self.python.version
257256
if ver in [2, 3]:
258-
# Get the highest version of the major series version if user only
259-
# gave us a version of '2', or '3'
260-
ver = max(
261-
v for v in self.get_valid_python_versions()
262-
if not isinstance(v, str) and v < ver + 1
257+
# use default Python version if user only set '2', or '3'
258+
return self.get_default_python_version_for_image(
259+
self.build.image,
260+
ver,
263261
)
264262
return ver
265263

@@ -296,6 +294,32 @@ def get_valid_python_versions_for_image(self, build_image):
296294
)
297295
return settings.DOCKER_IMAGE_SETTINGS[build_image]['python']['supported_versions']
298296

297+
def get_default_python_version_for_image(self, build_image, python_version):
298+
"""
299+
Return the default Python version for Docker image and Py2 or Py3.
300+
301+
:param build_image: the Docker image complete name, already validated
302+
(``readthedocs/build:4.0``, not just ``4.0``)
303+
:type build_image: str
304+
305+
:param python_version: major Python version (``2`` or ``3``) to get its
306+
default full version
307+
:type python_version: int
308+
309+
:returns: default version for the ``DOCKER_DEFAULT_VERSION`` if not
310+
``build_image`` found.
311+
"""
312+
if build_image not in settings.DOCKER_IMAGE_SETTINGS:
313+
build_image = '{}:{}'.format(
314+
settings.DOCKER_DEFAULT_IMAGE,
315+
self.default_build_image,
316+
)
317+
return (
318+
# For linting
319+
settings.DOCKER_IMAGE_SETTINGS[build_image]['python']
320+
['default_version'][python_version]
321+
)
322+
299323
def as_dict(self):
300324
config = {}
301325
for name in self.PUBLIC_ATTRIBUTES:
@@ -405,7 +429,9 @@ def validate_build(self):
405429
)
406430
# Update docker default settings from image name
407431
if build['image'] in settings.DOCKER_IMAGE_SETTINGS:
408-
self.env_config.update(settings.DOCKER_IMAGE_SETTINGS[build['image']])
432+
self.env_config.update(
433+
settings.DOCKER_IMAGE_SETTINGS[build['image']]
434+
)
409435

410436
# Allow to override specific project
411437
config_image = self.defaults.get('build_image')

readthedocs/config/tests/test_config.py

+22
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,28 @@ def test_python_version_default(self):
997997
build.validate()
998998
assert build.python.version == 3
999999

1000+
@pytest.mark.parametrize(
1001+
'image,default_version',
1002+
[
1003+
('1.0', 3.4),
1004+
('2.0', 3.5),
1005+
('3.0', 3.6),
1006+
('4.0', 3.7),
1007+
('5.0', 3.7),
1008+
('latest', 3.7),
1009+
('stable', 3.7),
1010+
],
1011+
)
1012+
def test_python_version_default_from_image(self, image, default_version):
1013+
build = self.get_build_config({
1014+
'build': {
1015+
'image': image,
1016+
},
1017+
})
1018+
build.validate()
1019+
assert build.python.version == int(default_version) # 2 or 3
1020+
assert build.python_full_version == default_version
1021+
10001022
@pytest.mark.parametrize('value', [2, 3])
10011023
def test_python_version_overrides_default(self, value):
10021024
build = self.get_build_config(

readthedocs/settings/base.py

+42-6
Original file line numberDiff line numberDiff line change
@@ -371,22 +371,58 @@ def USE_PROMOS(self): # noqa
371371
DOCKER_IMAGE = '{}:{}'.format(DOCKER_DEFAULT_IMAGE, DOCKER_DEFAULT_VERSION)
372372
DOCKER_IMAGE_SETTINGS = {
373373
'readthedocs/build:1.0': {
374-
'python': {'supported_versions': [2, 2.7, 3, 3.4]},
374+
'python': {
375+
'supported_versions': [2, 2.7, 3, 3.4],
376+
'default_version': {
377+
2: 2.7,
378+
3: 3.4,
379+
},
380+
},
375381
},
376382
'readthedocs/build:2.0': {
377-
'python': {'supported_versions': [2, 2.7, 3, 3.5]},
383+
'python': {
384+
'supported_versions': [2, 2.7, 3, 3.5],
385+
'default_version': {
386+
2: 2.7,
387+
3: 3.5,
388+
},
389+
},
378390
},
379391
'readthedocs/build:3.0': {
380-
'python': {'supported_versions': [2, 2.7, 3, 3.3, 3.4, 3.5, 3.6]},
392+
'python': {
393+
'supported_versions': [2, 2.7, 3, 3.3, 3.4, 3.5, 3.6],
394+
'default_version': {
395+
2: 2.7,
396+
3: 3.6,
397+
},
398+
},
381399
},
382400
'readthedocs/build:4.0': {
383-
'python': {'supported_versions': [2, 2.7, 3, 3.5, 3.6, 3.7]},
401+
'python': {
402+
'supported_versions': [2, 2.7, 3, 3.5, 3.6, 3.7],
403+
'default_version': {
404+
2: 2.7,
405+
3: 3.7,
406+
},
407+
},
384408
},
385409
'readthedocs/build:5.0': {
386-
'python': {'supported_versions': [2, 2.7, 3, 3.5, 3.6, 3.7, 'pypy3.5']},
410+
'python': {
411+
'supported_versions': [2, 2.7, 3, 3.5, 3.6, 3.7, 'pypy3.5'],
412+
'default_version': {
413+
2: 2.7,
414+
3: 3.7,
415+
},
416+
},
387417
},
388418
'readthedocs/build:6.0rc1': {
389-
'python': {'supported_versions': [2, 2.7, 3, 3.5, 3.6, 3.7, 3.8, 'pypy3.5']},
419+
'python': {
420+
'supported_versions': [2, 2.7, 3, 3.5, 3.6, 3.7, 3.8, 'pypy3.5'],
421+
'default_version': {
422+
2: 2.7,
423+
3: 3.7,
424+
},
425+
},
390426
},
391427
}
392428

0 commit comments

Comments
 (0)