Skip to content

Commit

Permalink
Drop Python 2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
dralley committed Dec 1, 2021
1 parent cd50896 commit 5561f3b
Show file tree
Hide file tree
Showing 25 changed files with 90 additions and 192 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
language: python
matrix:
include:
- python: "2.7"
env: TOXENV=py27
- python: "3.6"
env: TOXENV=py36
- python: "3.7"
Expand Down
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,6 @@ http://productmd.readthedocs.io/en/latest/
Building
--------

### Build requires

* Six: Python 2 and 3 Compatibility Library
* `pip install six`
* Fedora: `dnf install python-six python3-six`


### Build

To see all options run:
Expand Down
2 changes: 0 additions & 2 deletions productmd/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

# Copyright (C) 2015 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
Expand Down
30 changes: 14 additions & 16 deletions productmd/common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# pylint: disable=super-on-old-class


Expand Down Expand Up @@ -29,14 +28,15 @@
import sys
import re
import json
import http
import codecs
import contextlib
import ssl
import warnings
import urllib

import six
from six.moves.configparser import ConfigParser

from configparser import ConfigParser
from io import StringIO

VERSION = (1, 2)

Expand Down Expand Up @@ -165,7 +165,7 @@ def _urlopen(path):
# Older Python versions (<2.7.9) do not support it. In those cases the
# ssl module will not have the method to create the context.
kwargs['context'] = ssl._create_unverified_context()
return six.moves.urllib.request.urlopen(path, **kwargs)
return urllib.request.urlopen(path, **kwargs)


@contextlib.contextmanager
Expand All @@ -178,7 +178,7 @@ def open_file_obj(f, mode="r"):
:param mode: how to open the file
:type mode: string
"""
if isinstance(f, six.string_types):
if isinstance(f, str):
if f.startswith(("http://", "https://", "ftp://")):
file_obj = _urlopen(f)
yield file_obj
Expand All @@ -195,13 +195,13 @@ def _file_exists(path):
try:
file_obj = _urlopen(path)
file_obj.close()
except six.moves.urllib.error.HTTPError:
except urllib.error.HTTPError:
return False
return True
return os.path.exists(path)


class MetadataBase(object):
class MetadataBase:
def _assert_type(self, field, expected_types):
value = getattr(self, field)
for atype in expected_types:
Expand Down Expand Up @@ -269,7 +269,7 @@ def loads(self, s):
:param s: input data
:type s: str
"""
io = six.StringIO()
io = StringIO()
io.write(s)
io.seek(0)
self.load(io)
Expand All @@ -294,7 +294,7 @@ def dumps(self):
:rtype: str
"""
io = six.StringIO()
io = StringIO()
self.dump(io)
io.seek(0)
return io.read()
Expand All @@ -306,12 +306,10 @@ def parse_file(self, f):
f.seek(0)
elif hasattr(f, "seek"):
f.seek(0)
if six.PY3 and isinstance(f, six.moves.http_client.HTTPResponse):
if isinstance(f, http.client.HTTPResponse):
# HTTPResponse needs special handling in py3
reader = codecs.getreader("utf-8")
parser = json.load(reader(f))
else:
parser = json.load(f)
return parser

def build_file(self, parser, f):
Expand Down Expand Up @@ -343,7 +341,7 @@ def __init__(self, parent, metadata_type):
self.metadata_type = metadata_type

def _validate_version(self):
self._assert_type("version", six.string_types)
self._assert_type("version", [str])
self._assert_matches_re("version", [r"^\d+\.\d+$"])

@property
Expand Down Expand Up @@ -550,7 +548,7 @@ def __init__(self, *args, **kwargs):
ConfigParser.__init__(self, *args, **kwargs)
else:
kwargs["dict_type"] = SortedDict
super(SortedConfigParser, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
self.seen = set()

def optionxform(self, optionstr):
Expand All @@ -566,4 +564,4 @@ def option_lookup(self, section_option_list, default=None):
def read_file(self, *args, **kwargs):
if sys.version_info[0] == 2:
return self.readfp(*args, **kwargs)
return super(SortedConfigParser, self).read_file(*args, **kwargs)
return super().read_file(*args, **kwargs)
5 changes: 1 addition & 4 deletions productmd/compose.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-


# Copyright (C) 2015 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
Expand Down Expand Up @@ -49,7 +46,7 @@
)


class Compose(object):
class Compose:
"""
This class provides easy access to compose metadata.
Expand Down
49 changes: 22 additions & 27 deletions productmd/composeinfo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-


# Copyright (C) 2015 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
Expand Down Expand Up @@ -36,8 +33,6 @@
import productmd.common
from productmd.common import Header, RELEASE_VERSION_RE

import six


__all__ = (
"ComposeInfo",
Expand All @@ -47,9 +42,8 @@
)


if six.PY3:
def cmp(a, b):
return (a > b) - (a < b)
def cmp(a, b):
return (a > b) - (a < b)


# order matters - used in __cmp__
Expand Down Expand Up @@ -121,7 +115,7 @@ class ComposeInfo(productmd.common.MetadataBase):
"""

def __init__(self):
super(ComposeInfo, self).__init__()
super().__init__()

self.header = Header(self, "productmd.composeinfo") #: (:class:`.Header`) -- Metadata header
self.compose = Compose(self) #: (:class:`.Compose`) -- Compose details
Expand Down Expand Up @@ -265,7 +259,7 @@ class Compose(productmd.common.MetadataBase):
"""

def __init__(self, metadata):
super(Compose, self).__init__()
super().__init__()
self._section = "compose"
self._metadata = metadata
self.id = None
Expand Down Expand Up @@ -293,22 +287,22 @@ def __cmp__(self, other):
return 0

def _validate_id(self):
self._assert_type("id", list(six.string_types))
self._assert_type("id", [str])
self._assert_not_blank("id")
self._assert_matches_re("id", [r".*\d{8}(\.nightly|\.n|\.ci|\.test|\.t)?(\.\d+)?"])

def _validate_date(self):
self._assert_type("date", list(six.string_types))
self._assert_type("date", [str])
self._assert_matches_re("date", [r"^\d{8}$"])

def _validate_type(self):
self._assert_value("type", COMPOSE_TYPES)

def _validate_respin(self):
self._assert_type("respin", list(six.integer_types))
self._assert_type("respin", [int])

def _validate_label(self):
self._assert_type("label", [type(None)] + list(six.string_types))
self._assert_type("label", [type(None), str])
verify_label(self.label)

def _validate_final(self):
Expand Down Expand Up @@ -397,7 +391,7 @@ class BaseProduct(productmd.common.MetadataBase):
"""

def __init__(self, metadata):
super(BaseProduct, self).__init__()
super().__init__()
self._section = "base_product"
self._metadata = metadata
self.name = None #: (*str*) -- Product name, for example: "Fedora", "Red Hat Enterprise Linux"
Expand All @@ -421,20 +415,20 @@ def __str__(self):
return "%s-%s" % (self.short, self.version)

def _validate_name(self):
self._assert_type("name", list(six.string_types))
self._assert_type("name", [str])

def _validate_version(self):
"""If the version starts with a digit, it must be a sematic-versioning
style string.
"""
self._assert_type("version", list(six.string_types))
self._assert_type("version", [str])
self._assert_matches_re("version", [RELEASE_VERSION_RE])

def _validate_short(self):
self._assert_type("short", list(six.string_types))
self._assert_type("short", [str])

def _validate_type(self):
self._assert_type("type", list(six.string_types))
self._assert_type("type", [str])
self._assert_value("type", productmd.common.RELEASE_TYPES)

@property
Expand Down Expand Up @@ -478,7 +472,7 @@ class Release(BaseProduct):
"""

def __init__(self, metadata):
super(Release, self).__init__(metadata)
super().__init__(metadata)
self._section = "release"

self.name = None #: (*str*) -- Release name, for example: "Fedora", "Red Hat Enterprise Linux"
Expand All @@ -494,7 +488,7 @@ def __cmp__(self, other):
return BaseProduct.__cmp__(self, other)

def _validate_type(self):
self._assert_type("type", list(six.string_types))
self._assert_type("type", [str])
self._assert_value("type", productmd.common.RELEASE_TYPES)

def _validate_is_layered(self):
Expand Down Expand Up @@ -539,7 +533,7 @@ def deserialize_1_0(self, data):

class VariantBase(productmd.common.MetadataBase):
def __init__(self, metadata):
super(VariantBase, self).__init__()
super().__init__()
self._metadata = metadata
self.parent = None
self.variants = {}
Expand All @@ -548,7 +542,7 @@ def __repr__(self):
if hasattr(self, "compose"):
return u'<%s:%s>' % (self.__class__.__name__, self._metadata.compose.id)
else:
return super(VariantBase, self).__repr__()
return super().__repr__()

def __getitem__(self, name):
# There can be exceptions, like $variant-optional on top-level,
Expand Down Expand Up @@ -625,7 +619,7 @@ def get_variants(self, arch=None, types=None, recursive=False):
if "self" in types:
result.append(self)

for variant in six.itervalues(self.variants):
for variant in self.variants.values():
if types and variant.type not in types:
continue
if arch and arch not in variant.arches.union(["src"]):
Expand All @@ -642,8 +636,9 @@ class Variants(VariantBase):
"""
This class is a container for compose variants.
"""

def __init__(self, metadata):
super(Variants, self).__init__(metadata)
super().__init__(metadata)
self._section = "variants"

def serialize(self, data):
Expand Down Expand Up @@ -813,7 +808,7 @@ def __repr__(self):
return u'<%s:%s>' % (self.__class__.__name__, self.uid)

def _validate_id(self):
self._assert_type("id", list(six.string_types))
self._assert_type("id", [str])
self._assert_matches_re("id", [r"^[a-zA-Z0-9]+$"])

def _validate_uid(self):
Expand All @@ -828,7 +823,7 @@ def _validate_uid(self):
raise ValueError("UID '%s' doesn't align with parent UID '%s'" % (self.uid, uid))

def _validate_name(self):
self._assert_type("name", list(six.string_types))
self._assert_type("name", [str])
self._assert_not_blank("name")

def _validate_type(self):
Expand Down
2 changes: 1 addition & 1 deletion productmd/discinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class DiscInfo(productmd.common.MetadataBase):
"""

def __init__(self):
super(DiscInfo, self).__init__()
super().__init__()
self.timestamp = None #: Timestamp in float format
self.description = None #: Release description, for example: Fedora 20
self.arch = None #: Media architecture, for example: x86_64
Expand Down
4 changes: 1 addition & 3 deletions productmd/extra_files.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-

# Copyright (C) 2019 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
Expand Down Expand Up @@ -28,7 +26,7 @@

class ExtraFiles(productmd.common.MetadataBase):
def __init__(self):
super(ExtraFiles, self).__init__()
super().__init__()
self.header = Header(self, "productmd.extra_files")
self.compose = Compose(self)
self.extra_files = {}
Expand Down
Loading

0 comments on commit 5561f3b

Please sign in to comment.