SC006: DeprecatedAPIs

Overview

Property Value
ID SC006
Name DeprecatedAPIs
Group security
Severity WARNING

Description

Detects usage of deprecated Python standard library modules that have been deprecated in Python 3.9+ or are scheduled for removal in Python 3.12+.

Using deprecated modules poses both compatibility and security risks:

  • Code will break when modules are removed in future Python versions
  • Deprecated modules often lack security updates
  • Alternative modules provide better APIs and performance

What it checks

Deprecated modules detected

Module Reason Replacement
distutils Deprecated in Python 3.10, removed in 3.12 setuptools or build
imp Deprecated since Python 3.4 importlib
optparse Deprecated since Python 3.2 argparse
cgi Deprecated in Python 3.11 urllib.parse
cgitb Deprecated in Python 3.11 Standard logging
imghdr Deprecated in Python 3.11 python-magic
mailcap Deprecated in Python 3.11 mimetypes
msilib Deprecated in Python 3.11 N/A (Windows-specific)
nis Deprecated in Python 3.11 N/A (Unix-specific)
nntplib Deprecated in Python 3.11 Third-party alternatives
ossaudiodev Deprecated in Python 3.11 N/A (Linux-specific)
pipes Deprecated in Python 3.11 subprocess
sndhdr Deprecated in Python 3.11 python-magic
spwd Deprecated in Python 3.11 N/A (Unix-specific)
sunau Deprecated in Python 3.11 Third-party audio libraries
telnetlib Deprecated in Python 3.11 telnetlib3 or asyncio
uu Deprecated in Python 3.11 base64
xdrlib Deprecated in Python 3.11 struct or third-party

Import patterns detected

Both import styles are detected:

# Direct import
import distutils

# From import
from distutils.core import setup

# Submodule import
import distutils.util

Result states

  • PASSED: No deprecated module imports found
  • FAILED: Deprecated imports detected with file, line, and module name
  • SKIPPED: Unable to parse Python files (syntax errors)

How to fix

Replace distutils with setuptools

# Bad: deprecated distutils
from distutils.core import setup
from distutils.util import strtobool

# Good: use setuptools
from setuptools import setup
# For strtobool, implement your own or use a utility
def strtobool(val: str) -> bool:
    return val.lower() in ("y", "yes", "t", "true", "1")

Replace imp with importlib

# Bad: deprecated imp
import imp
module = imp.load_source("mymod", "path/to/module.py")

# Good: use importlib
import importlib.util
spec = importlib.util.spec_from_file_location("mymod", "path/to/module.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

Replace optparse with argparse

# Bad: deprecated optparse
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename")

# Good: use argparse
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-f", "--file", dest="filename")

Replace cgi with urllib.parse

# Bad: deprecated cgi
import cgi
form = cgi.FieldStorage()
value = cgi.escape(user_input)

# Good: use urllib.parse and html
from urllib.parse import parse_qs
from html import escape
query = parse_qs(environ.get("QUERY_STRING", ""))
safe_value = escape(user_input)

Replace pipes with subprocess

# Bad: deprecated pipes
import pipes
quoted = pipes.quote(user_input)

# Good: use shlex
import shlex
quoted = shlex.quote(user_input)

Replace telnetlib with telnetlib3

# Bad: deprecated telnetlib
import telnetlib
tn = telnetlib.Telnet("host", 23)

# Good: use telnetlib3 (async)
import asyncio
import telnetlib3

async def connect():
    reader, writer = await telnetlib3.open_connection("host", 23)
    # Use reader/writer

Replace uu with base64

# Bad: deprecated uu
import uu
uu.encode(in_file, out_file)

# Good: use base64
import base64
with open(in_file, "rb") as f:
    encoded = base64.b64encode(f.read())

Why WARNING severity?

This check is a WARNING because:

  • Deprecated modules still work in current Python versions
  • Migration may require significant refactoring
  • Some deprecated modules have no direct 1:1 replacements
  • Code should be updated before Python version upgrades

Configuration

Skip this check

[tool.pycmdcheck]
skip = ["SC006"]

CLI

pycmdcheck --skip SC006

Skip entire security group

pycmdcheck --skip-group security