Skip to content
Snippets Groups Projects
Commit 2edd547d authored by Grégoire Kubler's avatar Grégoire Kubler
Browse files

Merge branch 'feat/release_pip' into 'dev'

feat/release_pip

See merge request !116
parents 6a2d6585 dee865fd
No related branches found
No related tags found
2 merge requests!212Version 0.3.0,!116feat/release_pip
Pipeline #51142 passed
......@@ -12,6 +12,7 @@
#ifndef AIDGE_CORE_OPERATOR_SUB_H_
#define AIDGE_CORE_OPERATOR_SUB_H_
#include <array>
#include <memory>
#include <vector>
......
......@@ -14,11 +14,22 @@
#define AIDGE_DIRECTORIES_H_
#include <string> // std::string
#include <sstream> // std::stringstream
#include <algorithm>
#include <errno.h>
#include <iostream>
#include <sstream> // std::stringstream
#include <string> // std::string
#include <sys/stat.h>
#include <errno.h>
#ifndef _S_ISTYPE
#define _S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
#endif
#ifndef S_ISREG
#define S_ISREG(mode) _S_ISTYPE((mode), _S_IFREG)
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) _S_ISTYPE((mode), _S_IFDIR)
#endif
#ifdef WIN32
#include <direct.h>
......
[project]
name = "aidge_core"
description="Core algorithms for operators and graph of the AIDGE framework"
dependencies = [
"numpy>=1.21.6",
"Jinja2>=3.1.2"
]
requires-python = ">= 3.7"
readme = "README.md"
license = { file = "LICENSE" }
classifiers = [
"Development Status :: 2 - Pre-Alpha",
"Programming Language :: Python :: 3"
]
dynamic = ["version"] # defined in tool.setuptools_scm
[project.optional-dependencies]
test = [
"pytest"
]
[build-system]
requires = [
"setuptools>=64",
"setuptools_scm[toml]==7.1.0",
"cmake>=3.27.9",
"toml"
]
build-backend = "setuptools.build_meta"
#####################################################
# SETUPTOOLS
[tool.setuptools]
[tool.setuptools.packages.find]
where = ["."] # list of folders that contain the packages (["."] by default)
include = [ # package names should match these glob patterns (["*"] by default)
"aidge_core*"
]
exclude = [ # exclude packages matching these glob patterns (empty by default)
"aidge_core.unit_tests",
"aidge_core.unit_tests.static"
]
# SETUPTOOLS_SCM
[tool.setuptools_scm]
write_to = "aidge_core/_version.py"
#####################################################
# CIBUILDWHEEL
[tool.cibuildwheel]
build-frontend = "build"
test-requires = "pytest"
# FIXME: The ignored export test requires a to build the generated export via cmake.
# However due to a strange bug I haven't been able to properly link Python::Module to the export target
# Resulting in the need to link Python::Python which is the python interpreter.
# This suppresses the issue but sadly this target is not available on the cibuilwheel image.
# Hence the test is ignored. If you want to try and solve this bug go on.
# Just take care to increment the counter just below.
#
# Work time spent on this bug : 24h
test-command = "pytest --ignore={package}/aidge_core/unit_tests/test_export.py {package}/aidge_core/unit_tests"
# uncomment to run cibuildwheel locally on selected distros
# build=[
# "cp38-manylinux_x86_64",
# "cp39-manylinux_x86_64",
# "cp38-win_amd64",
# "cp39-win_amd64",
# "cp310-win_amd64",
# ]
### AIDGE DEPENDENCIES DECLARATION
[tool.cibuildwheel.environment]
# aidge_core do not rely on any aidge dependency, hence this string is empty
AIDGE_DEPENDENCIES = "" # format => "dep_1 dep_2 ... dep_n"
AIDGE_INSTALL="/AIDGE_INSTALL_CIBUILDWHEEL"
[tool.cibuildwheel.linux]
before-build = [
"bash .gitlab/ci/cibuildwheel_build_deps_before_build_wheel.sh /host"
]
[tool.cibuildwheel.windows]
before-build = [
"python -m pip debug -v",
"powershell -File .\\.gitlab\\ci\\cibuildwheel_build_deps_before_build_wheel.ps1"
]
#####################################################
# PYLINT
[tool.pylint.main]
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-allow-list = ["aidge_core", "torch", "tensorflow"]
# Files or directories to be skipped. They should be base names, not paths.
ignore = ["CVS"]
# List of module names for which member attributes should not be checked (useful
# for modules/projects where namespaces are manipulated during runtime and thus
# existing member attributes cannot be deduced by static analysis). It supports
# qualified module names, as well as Unix pattern matching.
ignored-modules = ["aidge_core"]
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use, and will cap the count on Windows to
# avoid hangs.
jobs = 1
# Control the amount of potential inferred values when inferring a single object.
# This can help the performance when dealing with large functions or complex,
# nested conditions.
limit-inference-results = 100
# Pickle collected data for later comparisons.
persistent = true
# Minimum Python version to use for version dependent checks. Will default to the
# version used to run pylint.
py-version = "3.7"
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode = true
[tool.pylint.basic]
# Naming style matching correct argument names.
argument-naming-style = "snake_case"
# Naming style matching correct attribute names.
attr-naming-style = "snake_case"
# Bad variable names which should always be refused, separated by a comma.
bad-names = ["foo", "bar", "baz", "toto", "tutu", "tata"]
# Naming style matching correct class attribute names.
class-attribute-naming-style = "any"
# Naming style matching correct class constant names.
class-const-naming-style = "UPPER_CASE"
# Naming style matching correct class names.
class-naming-style = "PascalCase"
# Naming style matching correct constant names.
const-naming-style = "UPPER_CASE"
# Minimum line length for functions/classes that require docstrings, shorter ones
# are exempt.
docstring-min-length = -1
# Naming style matching correct function names.
function-naming-style = "snake_case"
# Good variable names which should always be accepted, separated by a comma.
good-names = ["i", "j", "k", "ex", "Run", "_"]
# Naming style matching correct inline iteration names.
inlinevar-naming-style = "any"
# Naming style matching correct method names.
method-naming-style = "snake_case"
# Naming style matching correct module names.
module-naming-style = "snake_case"
# Regular expression which should only match function or class names that do not
# require a docstring.
no-docstring-rgx = "^_"
# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties. These
# decorators are taken in consideration only for invalid-name.
property-classes = ["abc.abstractproperty"]
# Naming style matching correct variable names.
variable-naming-style = "snake_case"
[tool.pylint.classes]
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods = ["__init__", "__new__", "setUp", "__post_init__"]
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected = ["_asdict", "_fields", "_replace", "_source", "_make"]
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg = ["cls"]
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg = ["cls"]
[tool.pylint.design]
# Maximum number of arguments for function / method.
max-args = 5
# Maximum number of attributes for a class (see R0902).
max-attributes = 7
# Maximum number of boolean expressions in an if statement (see R0916).
max-bool-expr = 5
# Maximum number of branch for function / method body.
max-branches = 12
# Maximum number of locals for function / method body.
max-locals = 15
# Maximum number of parents for a class (see R0901).
max-parents = 7
# Maximum number of public methods for a class (see R0904).
max-public-methods = 20
# Maximum number of return / yield for function / method body.
max-returns = 6
# Maximum number of statements in function / method body.
max-statements = 50
# Minimum number of public methods for a class (see R0903).
min-public-methods = 2
[tool.pylint.exceptions]
# Exceptions that will emit a warning when caught.
overgeneral-exceptions = ["BaseException", "Exception"]
[tool.pylint.format]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
# expected-line-ending-format =
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines = "^\\s*(# )?<?https?://\\S+>?$"
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren = 4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string = " "
# Maximum number of characters on a single line.
max-line-length = 200
# Maximum number of lines in a module.
max-module-lines = 1000
[tool.pylint.imports]
# Force import order to recognize a module as part of a third party library.
known-third-party = ["enchant"]
[tool.pylint.logging]
# The type of string formatting that logging methods do. `old` means using %
# formatting, `new` is for `{}` formatting.
logging-format-style = "old"
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules = ["logging"]
[tool.pylint."messages control"]
# Only show warnings with the listed confidence levels. Leave empty to show all.
# Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
confidence = ["HIGH", "CONTROL_FLOW", "INFERENCE", "INFERENCE_FAILURE", "UNDEFINED"]
# Disable the message, report, category or checker with the given id(s). You can
# either give multiple identifiers separated by comma (,) or put this option
# multiple times (only on the command line, not in the configuration file where
# it should appear only once). You can also use "--disable=all" to disable
# everything first and then re-enable specific checks. For example, if you want
# to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable = ["raw-checker-failed", "bad-inline-option", "locally-disabled", "file-ignored", "suppressed-message", "useless-suppression", "deprecated-pragma", "use-symbolic-message-instead", "use-implicit-booleaness-not-comparison-to-string", "use-implicit-booleaness-not-comparison-to-zero", "too-many-locals", "missing-class-docstring", "missing-function-docstring", "too-many-arguments", "protected-access", "too-many-branches", "too-many-ancestors", "wrong-import-order", "wrong-import-position"]
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where it
# should appear only once). See also the "--disable" option for examples.
enable = ["c-extension-no-member"]
[tool.pylint.method_args]
# List of qualified names (i.e., library.method) which require a timeout
# parameter e.g. 'requests.api.get,requests.api.post'
timeout-methods = ["requests.api.delete", "requests.api.get", "requests.api.head", "requests.api.options", "requests.api.patch", "requests.api.post", "requests.api.put", "requests.api.request"]
[tool.pylint.miscellaneous]
# List of note tags to take in consideration, separated by a comma.
notes = ["FIXME", "XXX", "TODO"]
# Regular expression of note tags to take in consideration.
# notes-rgx =
[tool.pylint.refactoring]
# Maximum number of nested blocks for function / method body
max-nested-blocks = 5
# Complete name of functions that never returns. When checking for inconsistent-
# return-statements if a never returning function is called then it will be
# considered as an explicit return statement and no message will be printed.
never-returning-functions = ["sys.exit", "argparse.parse_error"]
# Let 'consider-using-join' be raised when the separator to join on would be non-
# empty (resulting in expected fixes of the type: ``"- " + " - ".join(items)``)
suggest-join-with-non-empty-separator = true
[tool.pylint.reports]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
# 'convention', and 'info' which contain the number of messages in each category,
# as well as 'statement' which is the total number of statements analyzed. This
# score is used by the global evaluation report (RP0004).
evaluation = "10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)"
# Activate the evaluation score.
score = true
[tool.pylint.similarities]
# Comments are removed from the similarity computation
ignore-comments = true
# Docstrings are removed from the similarity computation
ignore-docstrings = true
# Minimum lines number of a similarity.
min-similarity-lines = 4
[tool.pylint.spelling]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions = 4
# List of comma separated words that should be considered directives if they
# appear at the beginning of a comment and should not be checked.
spelling-ignore-comment-directives = "fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:"
[tool.pylint.typecheck]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators = ["contextlib.contextmanager"]
# Tells whether missing members accessed in mixin class should be ignored. A
# class is considered mixin if its name matches the mixin-class-rgx option.
# Tells whether to warn about missing members when the owner of the attribute is
# inferred to be None.
ignore-none = true
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference can
# return multiple potential results while evaluating a Python object, but some
# branches might not be evaluated, which results in partial inference. In that
# case, it might be useful to still emit no-member and other checks for the rest
# of the inferred objects.
ignore-on-opaque-inference = true
# List of symbolic message names to ignore for Mixin members.
ignored-checks-for-mixins = ["no-member", "not-async-context-manager", "not-context-manager", "attribute-defined-outside-init"]
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes = ["optparse.Values", "thread._local", "_thread._local", "aidge.global_variables", "aidge.cells.abstract_cell.Trainable", "torch", "tensorflow"]
# Show a hint with possible names when a member name was not found. The aspect of
# finding the hint is based on edit distance.
missing-member-hint = true
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance = 1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices = 1
# Regex pattern to define which classes are considered mixins.
mixin-class-rgx = ".*[Mm]ixin"
[tool.pylint.variables]
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables = true
# List of strings which can identify a callback function by name. A callback name
# must start or end with one of those strings.
callbacks = ["cb_", "_cb"]
# A regular expression matching the name of dummy variables (i.e. expected to not
# be used).
dummy-variables-rgx = "_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_"
# Argument names that match this expression will be ignored.
ignored-argument-names = "_.*|^ignored_|^unused_"
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules = ["six.moves", "past.builtins", "future.builtins", "builtins", "io"]
#!/usr/bin/env python3
""" Aidge
#TODO To change
POC of the next framework named Aidge
"""
DOCLINES = (__doc__ or '').split("\n")
import sys
import os
# Python supported version checks
if sys.version_info[:2] < (3, 7):
raise RuntimeError("Python version >= 3.7 required.")
CLASSIFIERS = """\
Development Status :: 2 - Pre-Alpha
"""
import shutil
import pathlib
import subprocess
import multiprocessing
from math import ceil
import toml
from setuptools import setup, Extension
from setuptools import find_packages
from setuptools.command.build_ext import build_ext
def get_project_name() -> str:
return open(pathlib.Path().absolute() / "project_name.txt", "r").read()
def get_project_version() -> str:
aidge_root = pathlib.Path().absolute()
version = open(aidge_root / "version.txt", "r").read().strip()
return version
def get_project_name() -> str:
with open(pathlib.Path().absolute() / "pyproject.toml", "r") as file:
project_toml = toml.load(file)
return project_toml["project"]["name"]
class CMakeExtension(Extension):
def __init__(self, name):
super().__init__(name, sources=[])
class CMakeBuild(build_ext):
class CMakeBuild(build_ext):
def run(self):
# This lists the number of processors available on the machine
# The compilation will use half of them
......@@ -62,17 +41,42 @@ class CMakeBuild(build_ext):
os.chdir(str(build_temp))
# Impose to use the executable of the python
# used to launch setup.py to setup PythonInterp
param_py = "-DPYTHON_EXECUTABLE=" + sys.executable
compile_type = (
"Release"
if "AIDGE_PYTHON_BUILD_TYPE" not in os.environ
else os.environ["AIDGE_PYTHON_BUILD_TYPE"]
)
install_path = (
os.path.join(sys.prefix, "lib", "libAidge")
if "AIDGE_INSTALL" not in os.environ
else os.environ["AIDGE_INSTALL"]
)
build_gen = (
["-G", os.environ["AIDGE_BUILD_GEN"]]
if "AIDGE_BUILD_GEN" in os.environ
else []
)
self.spawn(
[
"cmake",
*build_gen,
str(cwd),
"-DTEST=OFF",
f"-DCMAKE_INSTALL_PREFIX:PATH={install_path}",
f"-DCMAKE_BUILD_TYPE={compile_type}",
"-DPYBIND=ON",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
"-DCOVERAGE=OFF",
]
)
compile_type = 'Debug'
install_path = os.path.join(sys.prefix, "lib", "libAidge") if "AIDGE_INSTALL" not in os.environ else os.environ["AIDGE_INSTALL"]
self.spawn(['cmake', str(cwd), param_py, '-DTEST=OFF', f'-DCMAKE_INSTALL_PREFIX:PATH={install_path}', f'-DCMAKE_BUILD_TYPE={compile_type}'])
if not self.dry_run:
self.spawn(['cmake', '--build', '.', '--config', compile_type, '-j', max_jobs])
self.spawn(['cmake', '--install', '.', '--config', compile_type])
self.spawn(
["cmake", "--build", ".", "--config", compile_type, "-j", max_jobs]
)
self.spawn(["cmake", "--install", ".", "--config", compile_type])
os.chdir(str(cwd))
aidge_package = build_lib / (get_project_name())
......@@ -83,8 +87,10 @@ class CMakeBuild(build_ext):
# Copy all shared object files from build_temp/lib to aidge_package
for root, _, files in os.walk(build_temp.absolute()):
for file in files:
if (file.endswith('.so') or file.endswith('.pyd')) and (root != str(aidge_package.absolute())):
currentFile=os.path.join(root, file)
if (file.endswith(".so") or file.endswith(".pyd")) and (
root != str(aidge_package.absolute())
):
currentFile = os.path.join(root, file)
shutil.copy(currentFile, str(aidge_package.absolute()))
# Copy version.txt in aidge_package
......@@ -92,22 +98,11 @@ class CMakeBuild(build_ext):
shutil.copy("version.txt", str(aidge_package.absolute()))
if __name__ == '__main__':
if __name__ == "__main__":
setup(
name=get_project_name(),
version=get_project_version(),
python_requires='>=3.7',
description=DOCLINES[0],
long_description_content_type="text/markdown",
long_description="\n".join(DOCLINES[2:]),
classifiers=[c for c in CLASSIFIERS.split('\n') if c],
packages=find_packages(where="."),
include_package_data=True,
ext_modules=[CMakeExtension(get_project_name())],
cmdclass={
'build_ext': CMakeBuild,
"build_ext": CMakeBuild,
},
zip_safe=False,
)
......@@ -23,10 +23,9 @@ void Aidge::Concat_OpImpl::forward() {
const DimSize_t axis = op.axis();
assert(op.getInput(0) && "missing input in Concat operator");
DataType datatypeFirstInput = op.getInput(0)->dataType();
for (IOIndex_t i = 1; i < mOp.nbInputs(); ++i) {
assert(op.getInput(i) && "missing input in Concat operator");
assert(op.getInput(i)->dataType() == datatypeFirstInput);
assert(op.getInput(i)->dataType() == op.getInput(0)->dataType());
}
DimSize_t outputAxisValue = 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment