Я возился с @dagster_type
и пытался создать пользовательский тип HtmlSoup
. В основном это необычная @dagster_type
оболочка вокруг объекта BeautifulSoup.
import requests
from bs4 import BeautifulSoup
from dagster import (
dagster_type,
input_hydration_config,
Selector,
Field,
String,
TypeCheck,
EventMetadataEntry
)
def max_depth(soup):
if hasattr(soup, "contents") and soup.contents:
return max([max_depth(child) for child in soup.contents]) + 1
else:
return 0
def html_soup_type_check(value):
if not isinstance(value, BeautifulSoup):
return TypeCheck(
success=False,
description=(
'HtmlSoup should be a BeautifulSoup Object, got '
'{type_}'
).format(type_=type(value))
)
if not hasattr(soup, "contents"):
return TypeCheck(
success=False,
description=(
'HtmlSoup has no contents, check that the URL has content'
)
)
return TypeCheck(
success=True,
description='HtmlSoup Summary Stats',
metadata_entries=[
EventMetadataEntry.text(
str(max_depth(value)),
'max_depth',
'Max Nested Depth of the Page Soup'
),
EventMetadataEntry.text(
str(set(tag.name for tag in value.find_all())),
'tag_names',
'All available tags in the Page Soup'
)
]
)
@input_hydration_config(
Selector(
{
'url': Field(
String,
is_optional=False,
description=(
'URL to be ingested and converted to a Soup Object'
)
)
}
)
)
def html_soup_input_hydration_config(context, selector):
url = selector['url']
res = requests.get(url, params={
'Content-type': 'text/html'
})
if (not res.status_code == 200):
return TypeCheck(
success=False,
description=(
'{status_code} ERROR, Check that URL: {url} is correct'
).format(status_code=res.status_code, url=url)
)
soup = BeautifulSoup(res.content, 'html.parser')
return HtmlSoup(soup)
@dagster_type(
name='HtmlSoup',
description=(
'The HTML extracted from a URL stored in '
'a BeautifulSoup object.'
),
type_check=html_soup_type_check,
input_hydration_config=html_soup_input_hydration_config
)
class HtmlSoup(BeautifulSoup):
pass
Это то, что я пробовал, но всякий раз, когда я пытаюсь вызвать solid, который использует, принимает в качестве ввода HtmlSoup
, например,
@solid
def get_url(context, soup: HtmlSoup):
return soup.contents
Я получаю эту ошибку
TypeError: объект 'NoneType' не вызывается
File "/Users/John/Documents/.../venv/lib/python3.7/site-packages/dagster/core/engine/engine_inprocess.py", line 241, in dagster_event_sequence_for_step
for step_event in check.generator(_core_dagster_event_sequence_for_step(step_context)):
File "/Users/John/Documents/.../venv/lib/python3.7/site-packages/dagster/core/engine/engine_inprocess.py", line 492, in _core_dagster_event_sequence_for_step
for input_name, input_value in _input_values_from_intermediates_manager(step_context).items():
File "/Users/John/Documents/.../venv/lib/python3.7/site-packages/dagster/core/engine/engine_inprocess.py", line 188, in _input_values_from_intermediates_manager
step_context, step_input.config_data
File "/Users/John/Documents/.../venv/lib/python3.7/site-packages/dagster/core/types/config_schema.py", line 73, in construct_from_config_value
return func(context, config_value)
File "/Users/John/Documents/.../custom_types/html_soup.py", line 82, in html_soup_input_hydration_config
return HtmlSoup(soup)
File "/Users/John/Documents/.../venv/lib/python3.7/site-packages/bs4/__init__.py", line 286, in __init__
markup = markup.read()
Я получил дополнительную информацию, которая говорит:
An exception was thrown during execution that is likely a framework error, rather than an error in user code.
Original error message: TypeError: 'NoneType' object is not callable
Я был сейчас немного покопаться во внутренностях декоратора @dagster_type
и о том, как работает декоратор @input_hydration_config
, но пока что он немного растерялся.
Цените любую помощь!