import json

from collections.abc import Iterable
from pathlib import Path
from typing import Optional
from urllib.request import urlopen, Request

from poetry.core.factory import Factory
try:
    from poetry.core.semver.helpers import parse_single_constraint
except ModuleNotFoundError:
    from poetry.core.semver import parse_single_constraint


VERSION_PARTS = ('major', 'minor', 'patch')


def get_versions(dependency: str, granularity: str = 'minor',
                 # ascending: bool = False, limit: Optional[int] = None,
                 # allow_prerelease: bool = False,
                 ) -> Iterable[str]:
    """Yield all versions of `dependency` considering version constraints

    Args:
        dependency: the name of the dependency
        granularity: yield only the newest patch version of each major/minor
            release
        ascending: count backwards from latest version, by default (not much
            use without the 'limit' arg)
        limit: maximum number of entries to return
        allow_prerelease: whether to include pre-release versions

    Yields:
        All versions of `dependency` that match the version constraints defined
        and in this project's pyproject.toml and the given `granularity`.

    """
    package = Factory().create_poetry(Path(__file__).parent).package
    for requirement in package.requires:
        if requirement.name == dependency:
            break
    else:
        raise ValueError(f"{package.name} has no dependency '{dependency}'")
    filtered_versions = [version for version in all_versions(dependency)
                         if requirement.constraint.allows(version)]
    parts = VERSION_PARTS[:VERSION_PARTS.index(granularity) + 1]
    result = {}
    for version in filtered_versions:
        key = tuple(getattr(version, part) for part in parts)
        result[key] = (max((result[key], version))
                       if key in result else version)
    return [str(version) for version in result.values()]


def all_versions(dependency):
    request = Request(f'https://pypi.org/pypi/{dependency}/json')
    response = urlopen(request)
    json_string = response.read().decode('utf8')
    json_data = json.loads(json_string)
    yield from (parse_single_constraint(version)
                for version in json_data['releases'])

@@ -87,24 +87,21 @@
  import 
-Opt
+Un
 ion
-al
 %0Afrom ur
@@ -394,32 +394,37 @@
 ef get_versions(
+%0A    
 dependency: str,
@@ -423,16 +423,20 @@
 cy: str,
+%0A   
  granula
@@ -451,30 +451,54 @@
 r = 
-'
+%22
 minor
-'
+%22
 ,%0A    
-         
+python: Union%5Bstr, None%5D = None,%0A
     
@@ -553,29 +553,16 @@
 = None,%0A
-             
     # al
@@ -591,33 +591,16 @@
  False,%0A
-                 
 ) -%3E Ite
@@ -840,16 +840,58 @@
 release%0A
+        python: version of python or None%0A
         
@@ -1362,16 +1362,61 @@
 package%0A
+    requirements = %5B%0A        requirement%0A    
     for 
@@ -1446,17 +1446,16 @@
 requires
-:
 %0A       
@@ -1492,36 +1492,38 @@
 ency
-:
 %0A    
+%5D%0A
     
-    break%0A    else
+if not requirements
 :%0A  
@@ -1601,148 +1601,599 @@
 '%22)%0A
+%0A
     
-filtered_
+def allowed(
 version
-s = %5Bversion for version in all_versions(dependency)%0A                         if requirement.constraint.allows(version)%5D
+):%0A        %22%22%22Return True if the version is allowed.%22%22%22%0A        if python is None:%0A            return any(%0A                requirement.constraint.allows(version) for requirement in requirements%0A            )%0A%0A        python_version = parse_single_constraint(python)%0A        for requirement in requirements:%0A            python_versions = parse_single_constraint(requirement.python_versions)%0A            if python_versions.allows(python_version) and requirement.constraint.allows(%0A                version%0A            ):%0A                return True%0A        return False%0A
 %0A   
@@ -2216,16 +2216,17 @@
 _PARTS%5B:
+ 
 VERSION_
@@ -2300,19 +2300,43 @@
 lter
-ed_versions
+(allowed, all_versions(dependency))
 :%0A  

Update noxutil.py