🔧 Added support for building socketw with conan v2
This commit is contained in:
parent
ab4b1a8202
commit
87a934a722
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ tmp/
|
||||
upload.*
|
||||
.idea/
|
||||
build_tmp.py
|
||||
__pycache__
|
||||
|
0
linter/__init__.py
Normal file
0
linter/__init__.py
Normal file
28
linter/check_import_conanfile.py
Normal file
28
linter/check_import_conanfile.py
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
from pylint.checkers import BaseChecker
|
||||
from pylint.interfaces import IAstroidChecker
|
||||
from astroid import nodes, Const, AssignName
|
||||
|
||||
|
||||
class ImportConanFile(BaseChecker):
|
||||
"""
|
||||
Import ConanFile from new 'conan' module
|
||||
"""
|
||||
|
||||
__implements__ = IAstroidChecker
|
||||
|
||||
name = "conan-import-conanfile"
|
||||
msgs = {
|
||||
"E9006": (
|
||||
"Import ConanFile from new module: `from conan import ConanFile`. Old import is deprecated in Conan v2.",
|
||||
"conan-import-conanfile",
|
||||
"Import ConanFile from new module: `from conan import ConanFile`. Old import is deprecated in Conan v2.",
|
||||
),
|
||||
}
|
||||
|
||||
def visit_importfrom(self, node: nodes.ImportFrom) -> None:
|
||||
basename = node.modname
|
||||
if basename == 'conans':
|
||||
names = [name for name, _ in node.names]
|
||||
if 'ConanFile' in names:
|
||||
self.add_message("conan-import-conanfile", node=node)
|
77
linter/check_import_errors.py
Normal file
77
linter/check_import_errors.py
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
from pylint.checkers import BaseChecker
|
||||
from pylint.interfaces import IAstroidChecker
|
||||
from astroid import nodes, Const, AssignName
|
||||
|
||||
|
||||
class ImportErrors(BaseChecker):
|
||||
"""
|
||||
Import errors from new 'conan' module
|
||||
"""
|
||||
|
||||
__implements__ = IAstroidChecker
|
||||
|
||||
name = "conan-import-errors"
|
||||
msgs = {
|
||||
"E9008": (
|
||||
"Import errors from new module: `from conan import errors`. Old import is deprecated in Conan v2.",
|
||||
"conan-import-errors",
|
||||
"Import errors from new module: `from conan import errors`. Old import is deprecated in Conan v2.",
|
||||
),
|
||||
}
|
||||
|
||||
def visit_importfrom(self, node: nodes.ImportFrom) -> None:
|
||||
basename = node.modname
|
||||
if basename == 'conans':
|
||||
names = [name for name, _ in node.names]
|
||||
if 'errors' in names:
|
||||
self.add_message("conan-import-errors", node=node)
|
||||
|
||||
|
||||
class ImportErrorsConanException(BaseChecker):
|
||||
"""
|
||||
Import errors from new 'conan' module
|
||||
"""
|
||||
|
||||
__implements__ = IAstroidChecker
|
||||
|
||||
name = "conan-import-error-conanexception"
|
||||
msgs = {
|
||||
"E9009": (
|
||||
"Import ConanException from new module: `from conan.errors import ConanException`. Old import is deprecated in Conan v2.",
|
||||
"conan-import-error-conanexception",
|
||||
"Import ConanException from new module: `from conan.errors import ConanException`. Old import is deprecated in Conan v2.",
|
||||
),
|
||||
}
|
||||
|
||||
def visit_importfrom(self, node: nodes.ImportFrom) -> None:
|
||||
basename = node.modname
|
||||
if basename == 'conans.errors':
|
||||
names = [name for name, _ in node.names]
|
||||
if 'ConanException' in names:
|
||||
self.add_message("conan-import-error-conanexception", node=node)
|
||||
|
||||
|
||||
class ImportErrorsConanInvalidConfiguration(BaseChecker):
|
||||
"""
|
||||
Import errors from new 'conan' module
|
||||
"""
|
||||
|
||||
__implements__ = IAstroidChecker
|
||||
|
||||
name = "conan-import-error-conaninvalidconfiguration"
|
||||
msgs = {
|
||||
"E9010": (
|
||||
"Import ConanInvalidConfiguration from new module: `from conan.errors import ConanInvalidConfiguration`. Old import is deprecated in Conan v2.",
|
||||
"conan-import-error-conaninvalidconfiguration",
|
||||
"Import ConanInvalidConfiguration from new module: `from conan.errors import ConanInvalidConfiguration`. Old import is deprecated in Conan v2.",
|
||||
),
|
||||
}
|
||||
|
||||
def visit_importfrom(self, node: nodes.ImportFrom) -> None:
|
||||
basename = node.modname
|
||||
if basename == 'conans.errors':
|
||||
names = [name for name, _ in node.names]
|
||||
if 'ConanInvalidConfiguration' in names:
|
||||
self.add_message("conan-import-error-conaninvalidconfiguration", node=node)
|
||||
|
30
linter/check_import_tools.py
Normal file
30
linter/check_import_tools.py
Normal file
@ -0,0 +1,30 @@
|
||||
import re
|
||||
from email.mime import base
|
||||
from pylint.checkers import BaseChecker
|
||||
from pylint.interfaces import IAstroidChecker
|
||||
from astroid import nodes, Const, AssignName
|
||||
|
||||
|
||||
class ImportTools(BaseChecker):
|
||||
"""
|
||||
Import tools following pattern 'from conan.tools.xxxx import yyyyy'
|
||||
"""
|
||||
|
||||
__implements__ = IAstroidChecker
|
||||
|
||||
name = "conan-import-tools"
|
||||
msgs = {
|
||||
"E9011": (
|
||||
"Import tools following pattern 'from conan.tools.xxxx import yyyyy' (https://docs.conan.io/en/latest/reference/conanfile/tools.html).",
|
||||
"conan-import-tools",
|
||||
"Import tools following pattern 'from conan.tools.xxxx import yyyyy' (https://docs.conan.io/en/latest/reference/conanfile/tools.html).",
|
||||
),
|
||||
}
|
||||
|
||||
def visit_importfrom(self, node: nodes.ImportFrom) -> None:
|
||||
basename = node.modname
|
||||
names = [name for name, _ in node.names]
|
||||
if basename == 'conan' and 'tools' in names:
|
||||
self.add_message("conan-import-tools", node=node)
|
||||
elif re.match(r'conan\.tools\.[^.]+\..+', basename):
|
||||
self.add_message("conan-import-tools", node=node)
|
30
linter/check_no_test_package_name.py
Normal file
30
linter/check_no_test_package_name.py
Normal file
@ -0,0 +1,30 @@
|
||||
from pylint.checkers import BaseChecker
|
||||
from pylint.interfaces import IAstroidChecker
|
||||
from astroid import nodes, Const, AssignName
|
||||
|
||||
|
||||
class NoPackageName(BaseChecker):
|
||||
"""
|
||||
Conanfile used for testing a package should NOT provide a name
|
||||
"""
|
||||
|
||||
__implements__ = IAstroidChecker
|
||||
|
||||
name = "conan-test-package-name"
|
||||
msgs = {
|
||||
"E9007": (
|
||||
"No 'name' attribute in test_package conanfile",
|
||||
"conan-test-no-name",
|
||||
"No 'name' attribute in test_package conanfile."
|
||||
)
|
||||
}
|
||||
|
||||
def visit_classdef(self, node: nodes) -> None:
|
||||
if node.basenames == ['ConanFile']:
|
||||
for attr in node.body:
|
||||
children = list(attr.get_children())
|
||||
if len(children) == 2 and \
|
||||
isinstance(children[0], AssignName) and \
|
||||
children[0].name == "name" and \
|
||||
isinstance(children[1], Const):
|
||||
self.add_message("conan-test-no-name", node=attr, line=attr.lineno)
|
39
linter/check_package_name.py
Normal file
39
linter/check_package_name.py
Normal file
@ -0,0 +1,39 @@
|
||||
from pylint.checkers import BaseChecker
|
||||
from pylint.interfaces import IAstroidChecker
|
||||
from astroid import nodes, Const, AssignName
|
||||
|
||||
|
||||
class PackageName(BaseChecker):
|
||||
"""
|
||||
All packages must have a lower-case name
|
||||
"""
|
||||
|
||||
__implements__ = IAstroidChecker
|
||||
|
||||
name = "conan-package-name"
|
||||
msgs = {
|
||||
"E9004": (
|
||||
"Reference name should be all lowercase",
|
||||
"conan-bad-name",
|
||||
"Use only lower-case on the package name: `name = 'foobar'`."
|
||||
),
|
||||
"E9005": (
|
||||
"Missing name attribute",
|
||||
"conan-missing-name",
|
||||
"The member attribute `name` must be declared: `name = 'foobar'`."
|
||||
)
|
||||
}
|
||||
|
||||
def visit_classdef(self, node: nodes) -> None:
|
||||
if node.basenames == ['ConanFile']:
|
||||
for attr in node.body:
|
||||
children = list(attr.get_children())
|
||||
if len(children) == 2 and \
|
||||
isinstance(children[0], AssignName) and \
|
||||
children[0].name == "name" and \
|
||||
isinstance(children[1], Const):
|
||||
value = children[1].as_string()
|
||||
if value.lower() != value:
|
||||
self.add_message("conan-bad-name", node=attr, line=attr.lineno)
|
||||
return
|
||||
self.add_message("conan-missing-name", node=node)
|
20
linter/conanv2_test_transition.py
Normal file
20
linter/conanv2_test_transition.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""
|
||||
|
||||
Pylint plugin/rules for test_package folder in Conan Center Index
|
||||
|
||||
"""
|
||||
|
||||
from pylint.lint import PyLinter
|
||||
from linter.check_import_conanfile import ImportConanFile
|
||||
from linter.check_no_test_package_name import NoPackageName
|
||||
from linter.check_import_errors import ImportErrorsConanException, ImportErrorsConanInvalidConfiguration, ImportErrors
|
||||
from linter.check_import_tools import ImportTools
|
||||
|
||||
|
||||
def register(linter: PyLinter) -> None:
|
||||
linter.register_checker(NoPackageName(linter))
|
||||
linter.register_checker(ImportConanFile(linter))
|
||||
linter.register_checker(ImportErrors(linter))
|
||||
linter.register_checker(ImportErrorsConanException(linter))
|
||||
linter.register_checker(ImportErrorsConanInvalidConfiguration(linter))
|
||||
linter.register_checker(ImportTools(linter))
|
20
linter/conanv2_transition.py
Normal file
20
linter/conanv2_transition.py
Normal file
@ -0,0 +1,20 @@
|
||||
"""
|
||||
|
||||
Pylint plugin/rules for conanfiles in Conan Center Index
|
||||
|
||||
"""
|
||||
|
||||
from pylint.lint import PyLinter
|
||||
from linter.check_package_name import PackageName
|
||||
from linter.check_import_conanfile import ImportConanFile
|
||||
from linter.check_import_errors import ImportErrorsConanException, ImportErrorsConanInvalidConfiguration, ImportErrors
|
||||
from linter.check_import_tools import ImportTools
|
||||
|
||||
|
||||
def register(linter: PyLinter) -> None:
|
||||
linter.register_checker(PackageName(linter))
|
||||
linter.register_checker(ImportConanFile(linter))
|
||||
linter.register_checker(ImportErrors(linter))
|
||||
linter.register_checker(ImportErrorsConanException(linter))
|
||||
linter.register_checker(ImportErrorsConanInvalidConfiguration(linter))
|
||||
linter.register_checker(ImportTools(linter))
|
30
linter/pylintrc_recipe
Normal file
30
linter/pylintrc_recipe
Normal file
@ -0,0 +1,30 @@
|
||||
[MASTER]
|
||||
load-plugins=linter.conanv2_transition,
|
||||
linter.transform_conanfile,
|
||||
linter.transform_imports
|
||||
|
||||
py-version=3.6
|
||||
recursive=no
|
||||
suggestion-mode=yes
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
disable=fixme,
|
||||
line-too-long,
|
||||
missing-module-docstring,
|
||||
missing-function-docstring,
|
||||
missing-class-docstring,
|
||||
invalid-name,
|
||||
wrong-import-order, # TODO: Remove
|
||||
import-outside-toplevel # TODO: Remove
|
||||
|
||||
enable=conan-bad-name,
|
||||
conan-missing-name,
|
||||
conan-import-conanfile
|
||||
|
||||
[REPORTS]
|
||||
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error) / statement) * 10))
|
||||
output-format=text
|
||||
reports=no
|
||||
score=no
|
||||
|
27
linter/pylintrc_testpackage
Normal file
27
linter/pylintrc_testpackage
Normal file
@ -0,0 +1,27 @@
|
||||
[MASTER]
|
||||
load-plugins=linter.conanv2_test_transition,
|
||||
linter.transform_conanfile,
|
||||
linter.transform_imports
|
||||
py-version=3.6
|
||||
recursive=no
|
||||
suggestion-mode=yes
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
disable=fixme,
|
||||
line-too-long,
|
||||
missing-module-docstring,
|
||||
missing-function-docstring,
|
||||
missing-class-docstring,
|
||||
invalid-name,
|
||||
wrong-import-order, # TODO: Remove
|
||||
import-outside-toplevel # TODO: Remove
|
||||
|
||||
enable=conan-test-no-name,
|
||||
conan-import-conanfile
|
||||
|
||||
[REPORTS]
|
||||
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error) / statement) * 10))
|
||||
output-format=text
|
||||
reports=no
|
||||
score=no
|
43
linter/recipe_linter.json
Normal file
43
linter/recipe_linter.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "recipe_linter_fatals",
|
||||
"severity": "error",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "(\\S+):(\\d+): \\[(F\\d+\\(\\S+\\)),\\s(.+?)?\\](.+)",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 5,
|
||||
"code": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "recipe_linter_errors",
|
||||
"severity": "error",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "(\\S+):(\\d+): \\[(E\\d+\\(\\S+\\)),\\s(.+?)?\\](.+)",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 5,
|
||||
"code": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "recipe_linter_warnings",
|
||||
"severity": "warning",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "(\\S+):(\\d+): \\[(W\\d+\\(\\S+\\)),\\s(.+?)?\\](.+)",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 5,
|
||||
"code": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
74
linter/transform_conanfile.py
Normal file
74
linter/transform_conanfile.py
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
# Class ConanFile doesn't declare all the valid members and functions,
|
||||
# some are injected by Conan dynamically to the class.
|
||||
|
||||
import textwrap
|
||||
import astroid
|
||||
from astroid.builder import AstroidBuilder
|
||||
from astroid.manager import AstroidManager
|
||||
|
||||
|
||||
def _settings_transform():
|
||||
module = AstroidBuilder(AstroidManager()).string_build(
|
||||
textwrap.dedent("""
|
||||
class Settings(object):
|
||||
os = None
|
||||
arch = None
|
||||
compiler = None
|
||||
build_type = None
|
||||
""")
|
||||
)
|
||||
return module['Settings']
|
||||
|
||||
def _user_info_build_transform():
|
||||
module = AstroidBuilder(AstroidManager()).string_build(
|
||||
textwrap.dedent("""
|
||||
class UserInfoBuild(defaultdict):
|
||||
pass
|
||||
""")
|
||||
)
|
||||
return module['UserInfoBuild']
|
||||
|
||||
|
||||
def register(_):
|
||||
pass
|
||||
|
||||
def transform_conanfile(node):
|
||||
"""Transform definition of ConanFile class so dynamic fields are visible to pylint"""
|
||||
|
||||
str_class = astroid.builtin_lookup("str")
|
||||
dict_class = astroid.builtin_lookup("dict")
|
||||
info_class = astroid.MANAGER.ast_from_module_name("conans.model.info").lookup(
|
||||
"ConanInfo")
|
||||
build_requires_class = astroid.MANAGER.ast_from_module_name(
|
||||
"conans.client.graph.graph_manager").lookup("_RecipeBuildRequires")
|
||||
file_copier_class = astroid.MANAGER.ast_from_module_name(
|
||||
"conans.client.file_copier").lookup("FileCopier")
|
||||
file_importer_class = astroid.MANAGER.ast_from_module_name(
|
||||
"conans.client.importer").lookup("_FileImporter")
|
||||
python_requires_class = astroid.MANAGER.ast_from_module_name(
|
||||
"conans.client.graph.python_requires").lookup("PyRequires")
|
||||
|
||||
dynamic_fields = {
|
||||
"conan_data": str_class,
|
||||
"build_requires": build_requires_class,
|
||||
"tool_requires": build_requires_class,
|
||||
"info_build": info_class,
|
||||
"user_info_build": [_user_info_build_transform()],
|
||||
"info": info_class,
|
||||
"copy": file_copier_class,
|
||||
"copy_deps": file_importer_class,
|
||||
"python_requires": [str_class, python_requires_class],
|
||||
"recipe_folder": str_class,
|
||||
"settings_build": [_settings_transform()],
|
||||
"settings_target": [_settings_transform()],
|
||||
"conf": dict_class,
|
||||
}
|
||||
|
||||
for f, t in dynamic_fields.items():
|
||||
node.locals[f] = [i for i in t]
|
||||
|
||||
|
||||
astroid.MANAGER.register_transform(
|
||||
astroid.ClassDef, transform_conanfile,
|
||||
lambda node: node.qname() == "conans.model.conan_file.ConanFile")
|
46
linter/transform_imports.py
Normal file
46
linter/transform_imports.py
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
import astroid
|
||||
from pylint.lint import PyLinter
|
||||
|
||||
"""
|
||||
Here we are transforming the imports to mimic future Conan v2 release. With
|
||||
these changes, built-in checks in Pylint will raise with different errors, so
|
||||
we are modifying the messages to point users in the right direction.
|
||||
"""
|
||||
|
||||
|
||||
def register(linter: PyLinter):
|
||||
msge1101 = linter.msgs_store._messages_definitions["E1101"]
|
||||
msge1101.msg += ". Please, check https://github.com/conan-io/conan-center-index/blob/master/docs/v2_linter.md"
|
||||
linter.msgs_store.register_message(msge1101)
|
||||
|
||||
msge0611 = linter.msgs_store._messages_definitions["E0611"]
|
||||
msge0611.msg += ". Please, check https://github.com/conan-io/conan-center-index/blob/master/docs/v2_linter.md"
|
||||
linter.msgs_store.register_message(msge0611)
|
||||
|
||||
def transform_tools(module):
|
||||
""" Transform import module """
|
||||
if 'get' in module.locals:
|
||||
del module.locals['get']
|
||||
if 'cross_building' in module.locals:
|
||||
del module.locals['cross_building']
|
||||
if 'rmdir' in module.locals:
|
||||
del module.locals['rmdir']
|
||||
if 'Version' in module.locals:
|
||||
del module.locals['Version']
|
||||
|
||||
def transform_errors(module):
|
||||
pass
|
||||
#if 'ConanInvalidConfiguration' in module.locals:
|
||||
# del module.locals['ConanInvalidConfiguration']
|
||||
#if 'ConanException' in module.locals:
|
||||
# del module.locals['ConanException']
|
||||
|
||||
|
||||
astroid.MANAGER.register_transform(
|
||||
astroid.Module, transform_tools,
|
||||
lambda node: node.qname() == "conans.tools")
|
||||
|
||||
astroid.MANAGER.register_transform(
|
||||
astroid.Module, transform_errors,
|
||||
lambda node: node.qname() == "conans.errors")
|
26
linter/yamllint_rules.yml
Normal file
26
linter/yamllint_rules.yml
Normal file
@ -0,0 +1,26 @@
|
||||
extends: default
|
||||
rules:
|
||||
document-start:
|
||||
level: error
|
||||
present: false
|
||||
document-end:
|
||||
level: error
|
||||
present: false
|
||||
empty-values:
|
||||
forbid-in-block-mappings: true
|
||||
forbid-in-flow-mappings: true
|
||||
line-length: disable
|
||||
indentation:
|
||||
level: error
|
||||
new-line-at-end-of-file:
|
||||
level: error
|
||||
trailing-spaces:
|
||||
level: error
|
||||
comments:
|
||||
level: error
|
||||
comments-indentation:
|
||||
level: error
|
||||
new-lines:
|
||||
type: unix
|
||||
key-duplicates:
|
||||
level: error
|
@ -1,5 +1,6 @@
|
||||
from conans import ConanFile, CMake, tools
|
||||
|
||||
from conan import ConanFile
|
||||
from conan.tools.files import get, collect_libs
|
||||
from conan.tools.cmake import CMakeToolchain, CMake, CMakeDeps, cmake_layout
|
||||
|
||||
class SocketwConan(ConanFile):
|
||||
name = "socketw"
|
||||
@ -7,14 +8,22 @@ class SocketwConan(ConanFile):
|
||||
url = "https://github.com/RigsOfRods/socketw/issues"
|
||||
description = "SocketW is a library which provides cross-platform socket abstraction"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
generators = "cmake"
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def requirements(self):
|
||||
for req in self.conan_data["requirements"]:
|
||||
self.requires(req)
|
||||
|
||||
def source(self):
|
||||
tools.get(**self.conan_data["sources"][self.version], strip_root=True)
|
||||
get(self, **self.conan_data["sources"][self.version], strip_root=True)
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.generate()
|
||||
deps = CMakeDeps(self)
|
||||
deps.generate()
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
@ -26,4 +35,4 @@ class SocketwConan(ConanFile):
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.libs = tools.collect_libs(self)
|
||||
self.cpp_info.libs = collect_libs(self)
|
||||
|
Loading…
x
Reference in New Issue
Block a user