Extract line length from pyproject.toml Black section (#1317)

This commit is contained in:
Charlie Marsh 2022-12-21 19:05:18 -05:00 committed by GitHub
parent 3b02da9d7b
commit 07dba46039
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 258 additions and 18 deletions

View file

@ -0,0 +1,65 @@
[build-system]
requires = [
# The minimum setuptools version is specific to the PEP 517 backend,
# and may be stricter than the version required in `setup.cfg`
"setuptools>=40.6.0,!=60.9.0",
"wheel",
# Must be kept in sync with the `install_requirements` in `setup.cfg`
"cffi>=1.12; platform_python_implementation != 'PyPy'",
"setuptools-rust>=0.11.4",
]
build-backend = "setuptools.build_meta"
[tool.black]
line-length = 79
target-version = ["py36"]
[tool.pytest.ini_options]
addopts = "-r s --capture=no --strict-markers --benchmark-disable"
markers = [
"skip_fips: this test is not executed in FIPS mode",
"supported: parametrized test requiring only_if and skip_message",
]
[tool.mypy]
show_error_codes = true
check_untyped_defs = true
no_implicit_reexport = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_unused_configs = true
strict_equality = true
[[tool.mypy.overrides]]
module = [
"pretend"
]
ignore_missing_imports = true
[tool.coverage.run]
branch = true
relative_files = true
source = [
"cryptography",
"tests/",
]
[tool.coverage.paths]
source = [
"src/cryptography",
"*.tox/*/lib*/python*/site-packages/cryptography",
"*.tox\\*\\Lib\\site-packages\\cryptography",
"*.tox/pypy/site-packages/cryptography",
]
tests =[
"tests/",
"*tests\\",
]
[tool.coverage.report]
exclude_lines = [
"@abc.abstractmethod",
"@abc.abstractproperty",
"@typing.overload",
"if typing.TYPE_CHECKING",
]

View file

@ -0,0 +1,91 @@
[metadata]
name = cryptography
version = attr: cryptography.__version__
description = cryptography is a package which provides cryptographic recipes and primitives to Python developers.
long_description = file: README.rst
long_description_content_type = text/x-rst
license = BSD-3-Clause OR Apache-2.0
url = https://github.com/pyca/cryptography
author = The Python Cryptographic Authority and individual contributors
author_email = cryptography-dev@python.org
project_urls =
Documentation=https://cryptography.io/
Source=https://github.com/pyca/cryptography/
Issues=https://github.com/pyca/cryptography/issues
Changelog=https://cryptography.io/en/latest/changelog/
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
License :: OSI Approved :: Apache Software License
License :: OSI Approved :: BSD License
Natural Language :: English
Operating System :: MacOS :: MacOS X
Operating System :: POSIX
Operating System :: POSIX :: BSD
Operating System :: POSIX :: Linux
Operating System :: Microsoft :: Windows
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy
Topic :: Security :: Cryptography
[options]
python_requires = >=3.6
include_package_data = True
zip_safe = False
package_dir =
=src
packages = find:
# `install_requires` must be kept in sync with `pyproject.toml`
install_requires =
cffi >=1.12
[options.packages.find]
where = src
exclude =
_cffi_src
_cffi_src.*
[options.extras_require]
test =
pytest>=6.2.0
pytest-benchmark
pytest-cov
pytest-subtests
pytest-xdist
pretend
iso8601
pytz
hypothesis>=1.11.4,!=3.79.2
docs =
sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1,!=5.2.0,!=5.2.0.post0
sphinx_rtd_theme
docstest =
pyenchant >= 1.6.11
twine >= 1.12.0
sphinxcontrib-spelling >= 4.0.1
sdist =
setuptools_rust >= 0.11.4
pep8test =
black
flake8
flake8-import-order
pep8-naming
# This extra is for OpenSSH private keys that use bcrypt KDF
# Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3
ssh =
bcrypt >= 3.1.5
[flake8]
ignore = E203,E211,W503,W504,N818
exclude = .tox,*.egg,.git,_build,.hypothesis
select = E,W,F,N,I
application-import-names = cryptography,cryptography_vectors,tests

View file

@ -0,0 +1,32 @@
//! Extract Black configuration settings from a pyproject.toml.
use std::path::Path;
use anyhow::Result;
use ruff::settings::types::PythonVersion;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
pub struct Black {
#[serde(alias = "line-length", alias = "line_length")]
pub line_length: Option<usize>,
#[serde(alias = "target-version", alias = "target_version")]
pub target_version: Option<Vec<PythonVersion>>,
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Tools {
black: Option<Black>,
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
struct Pyproject {
tool: Option<Tools>,
}
pub fn parse_black_options<P: AsRef<Path>>(path: P) -> Result<Option<Black>> {
let contents = std::fs::read_to_string(path)?;
Ok(toml::from_str::<Pyproject>(&contents)?
.tool
.and_then(|tool| tool.black))
}

View file

@ -11,13 +11,20 @@ use ruff::{
pep8_naming, pep8_naming,
}; };
use crate::black::Black;
use crate::plugin::Plugin; use crate::plugin::Plugin;
use crate::{parser, plugin}; use crate::{parser, plugin};
pub fn convert( pub fn convert(
flake8: &HashMap<String, Option<String>>, config: &HashMap<String, HashMap<String, Option<String>>>,
black: Option<&Black>,
plugins: Option<Vec<Plugin>>, plugins: Option<Vec<Plugin>>,
) -> Result<Pyproject> { ) -> Result<Pyproject> {
// Extract the Flake8 section.
let flake8 = config
.get("flake8")
.expect("Unable to find flake8 section in INI file");
// Extract all referenced check code prefixes, to power plugin inference. // Extract all referenced check code prefixes, to power plugin inference.
let mut referenced_codes: BTreeSet<CheckCodePrefix> = BTreeSet::default(); let mut referenced_codes: BTreeSet<CheckCodePrefix> = BTreeSet::default();
for (key, value) in flake8 { for (key, value) in flake8 {
@ -236,6 +243,19 @@ pub fn convert(
options.pep8_naming = Some(pep8_naming); options.pep8_naming = Some(pep8_naming);
} }
// Extract any settings from the existing `pyproject.toml`.
if let Some(black) = black {
if let Some(line_length) = &black.line_length {
options.line_length = Some(*line_length);
}
if let Some(target_version) = &black.target_version {
if let Some(target_version) = target_version.iter().min() {
options.target_version = Some(*target_version);
}
}
}
// Create the pyproject.toml. // Create the pyproject.toml.
Ok(Pyproject::new(options)) Ok(Pyproject::new(options))
} }
@ -255,7 +275,7 @@ mod tests {
#[test] #[test]
fn it_converts_empty() -> Result<()> { fn it_converts_empty() -> Result<()> {
let actual = convert(&HashMap::from([]), None)?; let actual = convert(&HashMap::from([]), None, None)?;
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
allowed_confusables: None, allowed_confusables: None,
dummy_variable_rgx: None, dummy_variable_rgx: None,
@ -303,7 +323,11 @@ mod tests {
#[test] #[test]
fn it_converts_dashes() -> Result<()> { fn it_converts_dashes() -> Result<()> {
let actual = convert( let actual = convert(
&HashMap::from([("max-line-length".to_string(), Some("100".to_string()))]), &HashMap::from([(
"flake8".to_string(),
HashMap::from([("max-line-length".to_string(), Some("100".to_string()))]),
)]),
None,
Some(vec![]), Some(vec![]),
)?; )?;
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
@ -353,7 +377,11 @@ mod tests {
#[test] #[test]
fn it_converts_underscores() -> Result<()> { fn it_converts_underscores() -> Result<()> {
let actual = convert( let actual = convert(
&HashMap::from([("max_line_length".to_string(), Some("100".to_string()))]), &HashMap::from([(
"flake8".to_string(),
HashMap::from([("max_line_length".to_string(), Some("100".to_string()))]),
)]),
None,
Some(vec![]), Some(vec![]),
)?; )?;
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
@ -403,7 +431,11 @@ mod tests {
#[test] #[test]
fn it_ignores_parse_errors() -> Result<()> { fn it_ignores_parse_errors() -> Result<()> {
let actual = convert( let actual = convert(
&HashMap::from([("max_line_length".to_string(), Some("abc".to_string()))]), &HashMap::from([(
"flake8".to_string(),
HashMap::from([("max_line_length".to_string(), Some("abc".to_string()))]),
)]),
None,
Some(vec![]), Some(vec![]),
)?; )?;
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
@ -453,7 +485,11 @@ mod tests {
#[test] #[test]
fn it_converts_plugin_options() -> Result<()> { fn it_converts_plugin_options() -> Result<()> {
let actual = convert( let actual = convert(
&HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]), &HashMap::from([(
"flake8".to_string(),
HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]),
)]),
None,
Some(vec![]), Some(vec![]),
)?; )?;
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
@ -509,9 +545,13 @@ mod tests {
fn it_converts_docstring_conventions() -> Result<()> { fn it_converts_docstring_conventions() -> Result<()> {
let actual = convert( let actual = convert(
&HashMap::from([( &HashMap::from([(
"docstring-convention".to_string(), "flake8".to_string(),
Some("numpy".to_string()), HashMap::from([(
"docstring-convention".to_string(),
Some("numpy".to_string()),
)]),
)]), )]),
None,
Some(vec![Plugin::Flake8Docstrings]), Some(vec![Plugin::Flake8Docstrings]),
)?; )?;
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
@ -597,7 +637,11 @@ mod tests {
#[test] #[test]
fn it_infers_plugins_if_omitted() -> Result<()> { fn it_infers_plugins_if_omitted() -> Result<()> {
let actual = convert( let actual = convert(
&HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]), &HashMap::from([(
"flake8".to_string(),
HashMap::from([("inline-quotes".to_string(), Some("single".to_string()))]),
)]),
None,
None, None,
)?; )?;
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {

View file

@ -11,6 +11,7 @@
clippy::too_many_lines clippy::too_many_lines
)] )]
pub mod black;
pub mod converter; pub mod converter;
mod parser; mod parser;
pub mod plugin; pub mod plugin;

View file

@ -17,6 +17,7 @@ use std::path::PathBuf;
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
use configparser::ini::Ini; use configparser::ini::Ini;
use flake8_to_ruff::black::parse_black_options;
use flake8_to_ruff::converter; use flake8_to_ruff::converter;
use flake8_to_ruff::plugin::Plugin; use flake8_to_ruff::plugin::Plugin;
@ -26,10 +27,14 @@ use flake8_to_ruff::plugin::Plugin;
long_about = None long_about = None
)] )]
struct Cli { struct Cli {
/// Path to the Flake8 configuration file (e.g., 'setup.cfg', 'tox.ini', or /// Path to the Flake8 configuration file (e.g., `setup.cfg`, `tox.ini`, or
/// '.flake8'). /// `.flake8`).
#[arg(required = true)] #[arg(required = true)]
file: PathBuf, file: PathBuf,
/// Optional path to a `pyproject.toml` file, used to ensure compatibility
/// with Black.
#[arg(long)]
pyproject: Option<PathBuf>,
/// List of plugins to enable. /// List of plugins to enable.
#[arg(long, value_delimiter = ',')] #[arg(long, value_delimiter = ',')]
plugin: Option<Vec<Plugin>>, plugin: Option<Vec<Plugin>>,
@ -43,13 +48,15 @@ fn main() -> Result<()> {
ini.set_multiline(true); ini.set_multiline(true);
let config = ini.load(cli.file).map_err(|msg| anyhow::anyhow!(msg))?; let config = ini.load(cli.file).map_err(|msg| anyhow::anyhow!(msg))?;
// Extract the Flake8 section. // Read the pyproject.toml file.
let flake8 = config let black = cli
.get("flake8") .pyproject
.expect("Unable to find flake8 section in INI file"); .map(parse_black_options)
.transpose()?
.flatten();
// Create the pyproject.toml. // Create Ruff's pyproject.toml section.
let pyproject = converter::convert(flake8, cli.plugin)?; let pyproject = converter::convert(&config, black.as_ref(), cli.plugin)?;
println!("{}", toml::to_string_pretty(&pyproject)?); println!("{}", toml::to_string_pretty(&pyproject)?);
Ok(()) Ok(())

View file

@ -13,7 +13,7 @@ use crate::checks::CheckCode;
use crate::checks_gen::CheckCodePrefix; use crate::checks_gen::CheckCodePrefix;
use crate::fs; use crate::fs;
#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Eq, Serialize, Deserialize, Hash)] #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
pub enum PythonVersion { pub enum PythonVersion {
Py33, Py33,