Skip to content

Commit

Permalink
Move related files to objects (#4102)
Browse files Browse the repository at this point in the history
* add related file class

* in progress

* test

* temp solution

* working

* fix

* test fixes

* test fixes

* Update demisto_sdk/commands/content_graph/parsers/related_files.py

Co-authored-by: Guy Afik <[email protected]>

* cr fixes

* pre commit fixes

---------

Co-authored-by: Guy Afik <[email protected]>
  • Loading branch information
YuvHayun and GuyAfik authored Mar 12, 2024
1 parent dbad080 commit 293b547
Show file tree
Hide file tree
Showing 22 changed files with 444 additions and 370 deletions.
18 changes: 0 additions & 18 deletions demisto_sdk/commands/common/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2134,21 +2134,3 @@ class IncidentState(str, Enum):
MarketplaceVersions.XSOAR.value,
MarketplaceVersions.MarketplaceV2.value,
]


class RelatedFileType(Enum):
YML = "YML"
JSON = "JSON"
README = "README"
DESCRIPTION = "DESCRIPTION"
IMAGE = "IMAGE"
DARK_SVG = "DARK_SVG"
LIGHT_SVG = "LIGHT_SVG"
CODE = "CODE"
TEST_CODE = "TEST_CODE"
SCHEMA = "SCHEMA"
XIF = "XIF"
PACK_IGNORE = "PACK_IGNORE"
SECRETS_IGNORE = "SECRETS_IGNORE"
AUTHOR_IMAGE = "AUTHOR_IMAGE"
RELEASE_NOTES = "RELEASE_NOTES"
34 changes: 19 additions & 15 deletions demisto_sdk/commands/common/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -1096,59 +1096,63 @@
"related_field": "",
},
# RM - READMEs
"readme_error": {"code": "RM100", "related_field": ""},
"image_path_error": {"code": "RM101", "related_field": ""},
"readme_error": {"code": "RM100", "related_field": "readme"},
"image_path_error": {"code": "RM101", "related_field": "readme"},
"readme_missing_output_context": {
"code": "RM102",
"related_field": "",
"related_field": "readme",
},
"error_starting_mdx_server": {
"code": "RM103",
"related_field": "",
"related_field": "readme",
},
"empty_readme_error": {
"code": "RM104",
"related_field": "",
"related_field": "readme",
},
"readme_equal_description_error": {
"code": "RM105",
"related_field": "",
"related_field": "readme",
},
"readme_contains_demisto_word": {
"code": "RM106",
"related_field": "",
"related_field": "readme",
},
"template_sentence_in_readme": {
"code": "RM107",
"related_field": "",
"related_field": "readme",
},
"invalid_readme_image_error": {
"code": "RM108",
"related_field": "",
"related_field": "readme",
},
"missing_readme_file": {
"code": "RM109",
"related_field": "",
"related_field": "readme",
},
"missing_commands_from_readme": {
"code": "RM110",
"related_field": "",
"related_field": "readme",
},
"error_uninstall_node": {
"code": "RM111",
"related_field": "",
"related_field": "readme",
},
"invalid_readme_relative_url_error": {
"code": "RM112",
"related_field": "",
"related_field": "readme",
},
"copyright_section_in_readme_error": {
"code": "RM113",
"related_field": "",
"related_field": "readme",
},
"image_does_not_exist": {
"code": "RM114",
"related_field": "",
"related_field": "readme",
},
"readme_lint_errors": {
"code": "RM115",
"related_field": "readme",
},
# RN - Release Notes
"missing_release_notes": {
Expand Down
3 changes: 2 additions & 1 deletion demisto_sdk/commands/common/hook_validations/readme.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ def check_readme_relative_url_paths(self, is_pack_readme: bool = False) -> list:

return error_list

@error_codes("RM114")
def verify_image_exist(self) -> bool:
"""Validate README images are actually exits.
Expand Down Expand Up @@ -825,7 +826,7 @@ def verify_demisto_in_readme_content(self):

return is_valid

# @error_codes("RM114")
@error_codes("RM115")
def has_no_markdown_lint_errors(self):
"""
Will check if the readme has markdownlint.
Expand Down
53 changes: 2 additions & 51 deletions demisto_sdk/commands/content_graph/objects/base_content.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from abc import ABC
from collections import defaultdict
from functools import lru_cache
from functools import cached_property, lru_cache
from pathlib import Path
from typing import (
TYPE_CHECKING,
Expand All @@ -27,11 +27,8 @@
PACKS_PACK_META_FILE_NAME,
GitStatuses,
MarketplaceVersions,
RelatedFileType,
)
from demisto_sdk.commands.common.content_constant_paths import CONTENT_PATH
from demisto_sdk.commands.common.files import TextFile
from demisto_sdk.commands.common.git_util import GitUtil
from demisto_sdk.commands.common.handlers import JSON_Handler
from demisto_sdk.commands.common.logger import logger
from demisto_sdk.commands.common.tools import set_value, write_dict
Expand Down Expand Up @@ -112,6 +109,7 @@ class Config:
)
orm_mode = True # allows using from_orm() method
allow_population_by_field_name = True # when loading from orm, ignores the aliases and uses the property name
keep_untouched = (cached_property,)

def __getstate__(self):
"""Needed to for the object to be pickled correctly (to use multiprocessing)"""
Expand Down Expand Up @@ -263,14 +261,6 @@ def upload(
# Implemented at the ContentItem/Pack level rather than here
raise NotImplementedError()

def get_related_content(self) -> Dict[RelatedFileType, Dict]:
"""Return a dict of the content item's related items with the list of possible paths, and the status of each related file.
Returns:
Dict[RelatedFileType, dict]: The dict of the content item's related items with the list of possible paths, and the status of each related file.
"""
return {}

@staticmethod
@lru_cache
def from_path(
Expand Down Expand Up @@ -330,45 +320,6 @@ def from_path(
def match(_dict: dict, path: Path) -> bool:
pass

@property
def related_content(self) -> Dict:
if not self.related_content_dict:
self.related_content_dict = self.get_related_content()
if self.old_base_content_object:
git_util = GitUtil()
remote, branch = git_util.handle_prev_ver(
self.old_base_content_object.git_sha # type: ignore[arg-type]
)
for file in self.related_content_dict.values():
for path in file["path"]:
status = git_util._check_file_status(path, remote, branch)
file["git_status"] = (
None
if (not status and not file["git_status"])
else GitStatuses(status)
)
return self.related_content_dict

def get_related_text_file(self, file_type: RelatedFileType) -> str:

for file_path in self.related_content[file_type]["path"]:
try:
if self.git_sha:
file = TextFile.read_from_git_path(
path=file_path,
tag=self.git_sha,
)
else:
file = TextFile.read_from_local_path(path=file_path)
self.related_content[file_type]["path"] = [file_path]
return file
except Exception as e:
logger.error(f"Failed to get related text file, error: {e}")
continue
raise NotAContentItemException(
f"The {file_type.value} file could not be found in the following paths: {', '.join(self.related_content[file_type]['path'])}"
)


class UnknownContent(BaseNode):
"""A model for non-existing content items used by existing content items."""
Expand Down
49 changes: 12 additions & 37 deletions demisto_sdk/commands/content_graph/objects/base_playbook.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
from typing import Callable, Dict, Optional
from functools import cached_property
from typing import Callable, Optional

import demisto_client

from demisto_sdk.commands.common.constants import (
PACKS_README_FILE_NAME,
MarketplaceVersions,
RelatedFileType,
)
from demisto_sdk.commands.content_graph.common import ContentType
from demisto_sdk.commands.content_graph.objects.content_item import ContentItem
from demisto_sdk.commands.content_graph.parsers.related_files import (
ImageRelatedFile,
ReadmeRelatedFile,
)
from demisto_sdk.commands.prepare_content.preparers.marketplace_incident_to_alert_playbooks_prepare import (
MarketplaceIncidentToAlertPlaybooksPreparer,
)
Expand Down Expand Up @@ -45,38 +48,10 @@ def prepare_for_upload(
def _client_upload_method(cls, client: demisto_client) -> Callable:
return client.import_playbook

def get_related_content(self) -> Dict[RelatedFileType, Dict]:
related_content_files = super().get_related_content()
related_content_files.update(
{
RelatedFileType.IMAGE: {
"path": [
str(
self.path.parents[1]
/ "doc_files"
/ str(self.path.parts[-1])
.replace(".yml", ".png")
.replace("playbook-", "")
),
str(self.path).replace(".yml", ".png"),
],
"git_status": None,
},
RelatedFileType.README: {
"path": [
str(
self.path.parent
/ str(self.path.parts[-1]).replace(
".yml", f"_{PACKS_README_FILE_NAME}"
)
)
],
"git_status": None,
},
}
)
return related_content_files
@cached_property
def readme(self) -> ReadmeRelatedFile:
return ReadmeRelatedFile(self.path, is_pack_readme=False, git_sha=self.git_sha)

@property
def readme(self) -> str:
return self.get_related_text_file(RelatedFileType.README)
@cached_property
def image(self) -> ImageRelatedFile:
return ImageRelatedFile(self.path, git_sha=self.git_sha)
57 changes: 21 additions & 36 deletions demisto_sdk/commands/content_graph/objects/integration.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from functools import cached_property
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional

Expand All @@ -7,14 +8,20 @@
from demisto_sdk.commands.content_graph.objects.base_content import (
BaseNode,
)
from demisto_sdk.commands.content_graph.parsers.related_files import (
DarkSVGRelatedFile,
DescriptionRelatedFile,
ImageRelatedFile,
LightSVGRelatedFile,
)

if TYPE_CHECKING:
# avoid circular imports
from demisto_sdk.commands.content_graph.objects.script import Script

from pydantic import BaseModel, Field

from demisto_sdk.commands.common.constants import MarketplaceVersions, RelatedFileType
from demisto_sdk.commands.common.constants import MarketplaceVersions
from demisto_sdk.commands.common.logger import logger
from demisto_sdk.commands.content_graph.common import ContentType, RelationshipType
from demisto_sdk.commands.content_graph.objects.integration_script import (
Expand Down Expand Up @@ -187,40 +194,18 @@ def save(self):
data["configuration"] = [param.dict(exclude_none=True) for param in self.params]
write_dict(self.path, data, indent=4)

def get_related_content(self) -> Dict[RelatedFileType, Dict]:
related_content_files = super().get_related_content()
related_content_files.update(
{
RelatedFileType.IMAGE: {
"path": [
str(self.path.parent / f"{self.path.parts[-2]}_image.png")
],
"git_status": None,
},
RelatedFileType.DARK_SVG: {
"path": [str(self.path.parent / f"{self.path.parts[-2]}_dark.svg")],
"git_status": None,
},
RelatedFileType.LIGHT_SVG: {
"path": [
str(self.path.parent / f"{self.path.parts[-2]}_light.svg")
],
"git_status": None,
},
RelatedFileType.DESCRIPTION: {
"path": [
str(self.path.parent / f"{self.path.parts[-2]}_description.md")
],
"git_status": None,
},
}
)
return related_content_files
@cached_property
def description_file(self) -> DescriptionRelatedFile:
return DescriptionRelatedFile(self.path, git_sha=self.git_sha)

@property
def description_file(self) -> str:
return self.get_related_text_file(RelatedFileType.DESCRIPTION)
@cached_property
def dark_svg(self) -> DarkSVGRelatedFile:
return DarkSVGRelatedFile(self.path, git_sha=self.git_sha)

@property
def image_file(self) -> str:
return self.related_content[RelatedFileType.IMAGE]["path"][0]
@cached_property
def light_svg(self) -> LightSVGRelatedFile:
return LightSVGRelatedFile(self.path, git_sha=self.git_sha)

@cached_property
def image(self) -> ImageRelatedFile:
return ImageRelatedFile(self.path, git_sha=self.git_sha)
Loading

0 comments on commit 293b547

Please sign in to comment.