Repository: frictionlessdata/frictionless-py

Issue:
Describe fails if there is a valid html
# Overview

https://discord.com/channels/695635777199145130/806182489865060423/813808449686863882


Discussion:

Patch:
diff --git a/data/text.html b/data/text.html
new file mode 100644
index 00000000..e6dd8ff7
--- /dev/null
+++ b/data/text.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+</head>
+<body>
+text
+</body>
+</html
diff --git a/frictionless/plugins/html.py b/frictionless/plugins/html.py
index 6cfec185..33683c90 100644
--- a/frictionless/plugins/html.py
+++ b/frictionless/plugins/html.py
@@ -100,16 +100,13 @@ class HtmlParser(Parser):
 
     def read_list_stream_create(self):
         pq = helpers.import_from_plugin("pyquery", plugin="html").PyQuery
-        dialect = self.resource.dialect
 
-        # Get Page content
+        # Get table
         page = pq(self.loader.text_stream.read(), parser="html")
-
-        # Find required table
-        if dialect.selector:
-            table = pq(page.find(dialect.selector)[0])
-        else:
-            table = page
+        tables = page.find(self.resource.dialect.selector)
+        table = pq(tables[0]) if tables else None
+        if not table:
+            return
 
         # Stream headers
         data = (
diff --git a/frictionless/resource.py b/frictionless/resource.py
index dfe1a728..2dab5985 100644
--- a/frictionless/resource.py
+++ b/frictionless/resource.py
@@ -691,10 +691,12 @@ class Resource(Metadata):
             stats? (bool): stream file completely and infer stats
         """
         if not self.closed:
-            raise FrictionlessException("Resource.infer canot be used on a open resource")
+            note = "Resource.infer canot be used on a open resource"
+            raise FrictionlessException(errors.ResourceError(note=note))
         with self:
             if not stats:
-                return self.pop("stats", None)
+                self.pop("stats", None)
+                return
             stream = self.row_stream or self.byte_stream
             helpers.pass_through(stream)
 
@@ -1023,7 +1025,10 @@ class Resource(Metadata):
         self.__fragment = fragment
         self.__field_positions = field_positions
         self.__fragment_positions = fragment_positions
-        self.stats["fields"] = len(self.schema.fields)
+        self.stats["fields"] = len(schema.fields)
+        # NOTE: review whether it's a proper place for this fallback to data resource
+        if not schema:
+            self.profile = "data-resource"
 
     def __read_detect_lookup(self):
         lookup = {}


Test patch:
diff --git a/tests/describe/test_main.py b/tests/describe/test_main.py
index 62c1b2ce..2e3b5d3a 100644
--- a/tests/describe/test_main.py
+++ b/tests/describe/test_main.py
@@ -126,3 +126,16 @@ def test_describe_non_tabular_resource_issue_641():
             "bytes": 262443,
         },
     }
+
+
+def test_describe_non_tabular_html_issue_715():
+    resource = describe("data/text.html")
+    assert resource == {
+        "path": "data/text.html",
+        "name": "text",
+        "profile": "data-resource",
+        "scheme": "file",
+        "format": "html",
+        "hashing": "md5",
+        "encoding": "utf-8",
+    }
diff --git a/tests/plugins/test_html.py b/tests/plugins/test_html.py
index 9eb2c7cd..71bad1d6 100644
--- a/tests/plugins/test_html.py
+++ b/tests/plugins/test_html.py
@@ -12,7 +12,6 @@ from frictionless.plugins.html import HtmlDialect
         ("data/table1.html", "table"),
         ("data/table2.html", "table"),
         ("data/table3.html", ".mememe"),
-        ("data/table4.html", ""),
     ],
 )
 def test_html_parser(source, selector):