Repository: HypothesisWorks/hypothesis

Issue:
Avoid use of __file__
It appears the use of `__file__` here is mostly unnecessary, or could be replaced with `importlib.resources`/`pkgutil`. See indygreg/PyOxidizer#69 for more info about why, but the tl;dr version is `__file__` is an optional attribute and should not be relied upon.

```
> GIT_PAGER=cat git grep -E '(__file__|ROOT|STDLIB)' hypothesis-python/src/hypothesis
hypothesis-python/src/hypothesis/core.py:ROOT = os.path.dirname(__file__)
hypothesis-python/src/hypothesis/core.py:STDLIB = os.path.dirname(os.__file__)
hypothesis-python/src/hypothesis/internal/escalation.py:    root = os.path.dirname(package.__file__)
hypothesis-python/src/hypothesis/provisional.py:    os.path.join(os.path.dirname(__file__), "vendor", "tlds-alpha-by-domain.txt")
```

At the moment, `import hypothesis` fails on any Python runtime that doesnt attach `__file__` to `hypothesis` *or* doesnt attach `__file__` to `os`.

As show there, `ROOT` and `STDLIB` are unused within the main runtime code.
If they are needed elsewhere, the definitions should be moved closer to the need, so that at least the top level `import hypothesis` works.

Loading of `tlds-alpha-by-domain.txt` should ideally be done using `importlib.resources` and backport ``importlib_resources`, however `pkgutil` could be used to avoid the need for the backport.  Using `pkgutil` would mean hypothesis doesn't work under PyOxidizer 0.4, however I expect that will be fixed soon.


Discussion:

Resolving patch:
diff --git a/hypothesis-python/src/hypothesis/core.py b/hypothesis-python/src/hypothesis/core.py
--- a/hypothesis-python/src/hypothesis/core.py
+++ b/hypothesis-python/src/hypothesis/core.py
@@ -24,7 +24,6 @@
 import contextlib
 import datetime
 import inspect
-import os
 import random as rnd_module
 import traceback
 import warnings
@@ -485,11 +484,6 @@ def new_given_argspec(original_argspec, generator_kwargs):
     )
 
 
-ROOT = os.path.dirname(__file__)
-
-STDLIB = os.path.dirname(os.__file__)
-
-
 class StateForActualGivenExecution(object):
     def __init__(self, test_runner, search_strategy, test, settings, random, had_seed):
         self.test_runner = test_runner
diff --git a/hypothesis-python/src/hypothesis/internal/escalation.py b/hypothesis-python/src/hypothesis/internal/escalation.py
--- a/hypothesis-python/src/hypothesis/internal/escalation.py
+++ b/hypothesis-python/src/hypothesis/internal/escalation.py
@@ -37,6 +37,9 @@
 
 
 def belongs_to(package):
+    if not hasattr(package, "__file__"):  # pragma: no cover
+        return lambda filepath: False
+
     root = os.path.dirname(package.__file__)
     cache = {text_type: {}, binary_type: {}}
 
diff --git a/hypothesis-python/src/hypothesis/provisional.py b/hypothesis-python/src/hypothesis/provisional.py
--- a/hypothesis-python/src/hypothesis/provisional.py
+++ b/hypothesis-python/src/hypothesis/provisional.py
@@ -45,13 +45,18 @@
 
 # This file is sourced from http://data.iana.org/TLD/tlds-alpha-by-domain.txt
 # The file contains additional information about the date that it was last updated.
-with open(
-    os.path.join(os.path.dirname(__file__), "vendor", "tlds-alpha-by-domain.txt")
-) as tld_file:
-    __header = next(tld_file)
-    assert __header.startswith("#")
-    TOP_LEVEL_DOMAINS = sorted((line.rstrip() for line in tld_file), key=len)
-TOP_LEVEL_DOMAINS.insert(0, "COM")
+try:
+    from importlib.resources import read_text  # type: ignore
+except ImportError:
+    # If we don't have importlib.resources (Python 3.7+) or the importlib_resources
+    # backport available, fall back to __file__ and hope we're on a filesystem.
+    f = os.path.join(os.path.dirname(__file__), "vendor", "tlds-alpha-by-domain.txt")
+    with open(f) as tld_file:
+        _tlds = tld_file.read().splitlines()
+else:  # pragma: no cover  # new in Python 3.7
+    _tlds = read_text("hypothesis.vendor", "tlds-alpha-by-domain.txt").splitlines()
+assert _tlds[0].startswith("#")
+TOP_LEVEL_DOMAINS = ["COM"] + sorted(_tlds[1:], key=len)
 
 
 class DomainNameStrategy(SearchStrategy):


Test patch: