Skip to content

Commit

Permalink
update version 1.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nhatnamnguyengtvthcm committed Aug 30, 2023
2 parents b84e4cc + 00e6afb commit ef926b1
Show file tree
Hide file tree
Showing 45 changed files with 750 additions and 649 deletions.
23 changes: 6 additions & 17 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,9 @@ jobs:
name: Lint
runs-on: ubuntu-20.04
steps:
- uses: actions/[email protected]
- name: Set Up Python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install/Update build dependencies
run: |
python -m pip install --upgrade setuptools
python -m pip install --upgrade pip
- name: Install Poetry
run: |
curl -sL https://install.python-poetry.org | python -
- name: Update Pip
run: poetry run pip install -U pip setuptools
- name: Install Dependencies
run: poetry install
- uses: pre-commit/[email protected]
- uses: actions/checkout@v3
- name: Set up Python 3.8
uses: actions/setup-python@v4
with:
python-version: '3.8'
- uses: pre-commit/[email protected]
17 changes: 10 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@ repos:
args:
- --py36-plus

- repo: local
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
name: mypy
entry: poetry run mypy
language: system
require_serial: true
pass_filenames: false
- id: mypy
files: sphinx_needs/.*
args: []
additional_dependencies:
- sphinx==6
- types-docutils
- types-jsonschema
- types-requests

- repo: https://github.com/python-poetry/poetry
rev: 1.5.0
Expand Down
63 changes: 31 additions & 32 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,51 +81,50 @@ line-length = 120
profile = "black"

[tool.mypy]
files = "sphinx_needs"
strict = true
show_error_codes = true
implicit_reexport = true
files = "sphinx_needs"
ignore_missing_imports = true
namespace_packages = true
warn_unused_ignores = false
disallow_any_generics = true
disallow_subclassing_any = true
# disallow_any_unimported = true
# disallow_any_explicit = true
# disallow_any_expr = true
# disallow_any_decorated = true

[[tool.mypy.overrides]]
module = [
"matplotlib.*",
"numpy.*",
"requests_file",
"sphinx_data_viewer.*",
"sphinxcontrib.plantuml.*",
]
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = [
'sphinx_needs.api.need',
'sphinx_needs.data',
'sphinx_needs.diagrams_common',
'sphinx_needs.directives.need',
'sphinx_needs.directives.needbar',
'sphinx_needs.directives.needextend',
'sphinx_needs.directives.needextract',
'sphinx_needs.directives.needfilter',
'sphinx_needs.directives.needflow',
'sphinx_needs.directives.needgantt',
'sphinx_needs.directives.needlist',
'sphinx_needs.directives.needpie',
'sphinx_needs.directives.needsequence',
'sphinx_needs.directives.needtable',
'sphinx_needs.directives.needuml',
'sphinx_needs.directives.utils',
'sphinx_needs.environment',
'sphinx_needs.external_needs',
'sphinx_needs.filter_common',
'sphinx_needs.functions.common',
'sphinx_needs.functions.functions',
'sphinx_needs.layout',
'sphinx_needs.needs',
'sphinx_needs.needsfile',
'sphinx_needs.roles.need_incoming',
'sphinx_needs.roles.need_outgoing',
'sphinx_needs.roles.need_part',
'sphinx_needs.roles.need_ref',
'sphinx_needs.services.github',
'sphinx_needs.services.manager',
'sphinx_needs.utils',
'sphinx_needs.warnings',
]
ignore_errors = true

[[tool.mypy.overrides]]
module = [
"sphinx_needs.directives.needextend"
]
# TODO dynamically overriding TypeDict keys is a bit tricky
disable_error_code = "literal-required"

[[tool.mypy.overrides]]
module = [
"sphinx_needs.data"
]
disable_error_code = ["attr-defined", "no-any-return"]


[build-system]
requires = ["setuptools", "poetry_core>=1.0.8"] # setuptools for deps like plantuml
build-backend = "poetry.core.masonry.api"
Expand Down
22 changes: 10 additions & 12 deletions sphinx_needs/api/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
All functions here are available under ``sphinxcontrib.api``. So do not import this module directly.
"""
from typing import Any, Callable, List, Optional
from typing import Callable, List, Optional

from docutils.parsers.rst import directives
from sphinx.application import Sphinx
from sphinx.util.logging import SphinxLoggerAdapter

from sphinx_needs.api.exceptions import NeedsApiConfigException, NeedsApiConfigWarning
from sphinx_needs.config import NEEDS_CONFIG, NeedsSphinxConfig
from sphinx_needs.data import NeedsInfoType
from sphinx_needs.functions import register_func
from sphinx_needs.functions.functions import DynamicFunction

Expand Down Expand Up @@ -84,13 +85,9 @@ def add_extra_option(app: Sphinx, name: str) -> None:
:param name: Name as string of the extra option
:return: None
"""

extra_options = NEEDS_CONFIG.create_or_get("extra_options", dict)

if name in extra_options:
if name in NEEDS_CONFIG.extra_options:
raise NeedsApiConfigWarning(f"Option {name} already registered.")

NEEDS_CONFIG.add("extra_options", {name: directives.unchanged}, dict, append=True)
NEEDS_CONFIG.extra_options[name] = directives.unchanged


def add_dynamic_function(app: Sphinx, function: DynamicFunction, name: Optional[str] = None) -> None:
Expand Down Expand Up @@ -121,7 +118,7 @@ def my_function(app, need, needs, *args, **kwargs):


# 'Need' is untyped, so we temporarily use 'Any' here
WarningCheck = Callable[[Any, SphinxLoggerAdapter], bool]
WarningCheck = Callable[[NeedsInfoType, SphinxLoggerAdapter], bool]


def add_warning(
Expand All @@ -138,8 +135,6 @@ def add_warning(
:param filter_string: filter_string to use for the warning
:return: None
"""
warnings_option = NEEDS_CONFIG.create_or_get("warnings", dict)

if function is None and filter_string is None:
raise NeedsApiConfigException("Function or filter_string must be given for add_warning_func")

Expand All @@ -150,7 +145,10 @@ def add_warning(

warning_check = function or filter_string

if name in warnings_option:
if warning_check is None:
raise NeedsApiConfigException("either function or filter_string must be given")

if name in NEEDS_CONFIG.warnings:
raise NeedsApiConfigException(f"Warning {name} already registered.")

NEEDS_CONFIG.add("warnings", {name: warning_check}, dict, append=True)
NEEDS_CONFIG.warnings[name] = warning_check
3 changes: 1 addition & 2 deletions sphinx_needs/api/need.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ def run():
"docname": docname,
"doctype": doctype,
"lineno": lineno,
# "target_node": target_node,
"target_id": need_id,
"external_url": external_url,
"content_node": None, # gets set after rst parsing
Expand Down Expand Up @@ -346,7 +345,7 @@ def run():
"is_modified": False, # needed by needextend
"modifications": 0, # needed by needextend
}
needs_extra_option_names = NEEDS_CONFIG.get("extra_options").keys()
needs_extra_option_names = list(NEEDS_CONFIG.extra_options)
_merge_extra_options(needs_info, kwargs, needs_extra_option_names)

needs_global_options = needs_config.global_options
Expand Down
7 changes: 3 additions & 4 deletions sphinx_needs/builder.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import os
from typing import Iterable, Optional, Set
from typing import Iterable, List, Optional, Set

from docutils import nodes
from sphinx import version_info
from sphinx.application import Sphinx
from sphinx.builders import Builder

from sphinx_needs.config import NeedsSphinxConfig
from sphinx_needs.data import SphinxNeedsData
from sphinx_needs.data import NeedsInfoType, SphinxNeedsData
from sphinx_needs.filter_common import filter_needs
from sphinx_needs.logging import get_logger
from sphinx_needs.needsfile import NeedsList
Expand All @@ -28,7 +28,6 @@ def write_doc(self, docname: str, doctree: nodes.document) -> None:
def finish(self) -> None:
env = unwrap(self.env)
data = SphinxNeedsData(env)
needs = data.get_or_create_needs().values() # We need a list of needs for later filter checks
filters = data.get_or_create_filters()
version = getattr(env.config, "version", "unset")
needs_list = NeedsList(env.config, self.outdir, self.srcdir)
Expand All @@ -49,7 +48,7 @@ def finish(self) -> None:
needs_list.wipe_version(version)

filter_string = needs_config.builder_filter
filtered_needs = filter_needs(self.app, needs, filter_string)
filtered_needs: List[NeedsInfoType] = filter_needs(self.app, data.get_or_create_needs().values(), filter_string)

for need in filtered_needs:
needs_list.add_need(version, need)
Expand Down
59 changes: 28 additions & 31 deletions sphinx_needs/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
from __future__ import annotations

from dataclasses import MISSING, dataclass, field, fields
from typing import Any, Callable
from typing import TYPE_CHECKING, Any, Callable

from sphinx.application import Sphinx
from sphinx.config import Config as _SphinxConfig

from sphinx_needs.defaults import DEFAULT_DIAGRAM_TEMPLATE, NEEDS_TABLES_CLASSES

if TYPE_CHECKING:
from sphinx.util.logging import SphinxLoggerAdapter

from sphinx_needs.data import NeedsInfoType


class Config:
"""
Expand All @@ -20,38 +25,30 @@ class Config:
"""

def __init__(self) -> None:
self.configs: dict[str, Any] = {}

def add(
self, name: str, value: Any, option_type: type = str, append: bool = False, overwrite: bool = False
) -> None:
if name not in self.configs:
self.configs[name] = option_type()
elif not isinstance(self.configs[name], option_type):
raise Exception(
f"Type of needs config option {name} is {type(self.configs[name])}," f"but {option_type} is given"
)
self._extra_options: dict[str, Callable[[str], Any]] = {}
self._warnings: dict[str, str | Callable[[NeedsInfoType, SphinxLoggerAdapter], bool]] = {}

if not append:
self.configs[name] = value
else:
if isinstance(self.configs[name], dict):
self.configs[name] = {**self.configs[name], **value}
else:
self.configs[name] += value
def clear(self) -> None:
self._extra_options = {}
self._warnings = {}

@property
def extra_options(self) -> dict[str, Callable[[str], Any]]:
"""Options that are dynamically added to `NeedDirective` & `NeedserviceDirective`,
after the config is initialized.
def create(self, name: str, option_type: Callable[[], Any] = str, overwrite: bool = False) -> None:
if name in self.configs and not overwrite:
raise Exception(f"option {name} exists.")
self.configs[name] = option_type()
These fields are also added to the each needs data item.
def create_or_get(self, name: str, option_type: Callable[[], Any] = str) -> Any:
if name not in self.configs:
self.configs[name] = option_type()
return self.configs[name]
:returns: Mapping of name to validation function
"""
return self._extra_options

def get(self, name: str) -> Any:
return self.configs[name]
@property
def warnings(self) -> dict[str, str | Callable[[NeedsInfoType, SphinxLoggerAdapter], bool]]:
"""Warning handlers that are added by the user,
then called at the end of the build.
"""
return self._warnings


NEEDS_CONFIG = Config()
Expand Down Expand Up @@ -148,7 +145,7 @@ def __setattr__(self, name: str, value: Any) -> None:
default=DEFAULT_DIAGRAM_TEMPLATE,
metadata={"rebuild": "html", "types": (str,)},
)
functions: list[Any] = field(default_factory=list, metadata={"rebuild": "html", "types": (list,)})
functions: list[Callable[..., Any]] = field(default_factory=list, metadata={"rebuild": "html", "types": (list,)})
global_options: dict[str, Any] = field(default_factory=dict, metadata={"rebuild": "html", "types": (dict,)})
duration_option: str = field(default="duration", metadata={"rebuild": "html", "types": (str,)})
completion_option: str = field(default="completion", metadata={"rebuild": "html", "types": (str,)})
Expand All @@ -174,7 +171,7 @@ def __setattr__(self, name: str, value: Any) -> None:
extra_links: list[dict[str, Any]] = field(default_factory=list, metadata={"rebuild": "html", "types": ()})
"""List of additional links, which can be used by setting related option
Values needed for each new link:
* name (will also be the option name)
* option (will also be the option name)
* incoming
* copy_link (copy to common links data. Default: True)
* color (used for needflow. Default: #000000)
Expand Down
Loading

0 comments on commit ef926b1

Please sign in to comment.