Idea: Use case for a VersionInfoIterator?
See original GitHub issueSituation
For example, if we want to start from a certain version and get the next 3 versions we could do that:
v = VersionInfo.parse("1.2.3-rc.3")
for _ in range(3):
print(v.next_version(part="prerelease"))
This would work, but maybe we could use the iterator protocol for that.
Proposed Solution
The solution is very rough, but that’s on purpose. It’s a minimal example to demonstrate the idea and not get distracted by other methods. So I know, this would need fine-tuning (add properties, protect from invalid datatypes etc.).
class VersionInfoIterator:
"""Iterator over VersionInfo objects"""
def __init__(self, version, part, steps=10):
self.version = version
self.part = part
self._steps = steps
def __iter__(self):
return self
def __repr__(self):
cls = type(self)
return "{}(version={!r}, part={!r}, steps={})".format(cls.__name__,
self.version, self.part, self._steps)
def __next__(self):
if not self.steps:
raise StopIteration
self._steps -= 1
self.version = self.version.next_version(self.part)
return self.version
An implementation could look like this:
from semver import VersionInfo, VersionInfoIterator
>>> v = VersionInfo.parse("1.2.3-rc.3")
>>> vit = VersionInfoIterator(v, "prerelease", steps=3)
>>> next(vit)
VersionInfo(major=1, minor=2, patch=3, prerelease='rc.4', build=None)
>>> next(vit)
VersionInfo(major=1, minor=2, patch=3, prerelease='rc.5', build=None)
>>> vit.part = "minor"
>>> next(vit)
VersionInfo(major=1, minor=3, patch=0, prerelease=None, build=None)
>>> next(vit)
Traceback (most recent call last)
...
StopIteration
# or
>>> vit = VersionInfoIterator(v, "prerelease", steps=3)
>>> list(vit)
[VersionInfo(major=1, minor=2, patch=3, prerelease='rc.4', build=None),
VersionInfo(major=1, minor=2, patch=3, prerelease='rc.5', build=None),
VersionInfo(major=1, minor=2, patch=3, prerelease='rc.6', build=None)]
Questions
- Would such an iterator be useful?
- Is it necessary or is first example above enough when iterating?
- If you think it could be useful, would you change something in
__init__
?
Actually, I’m not sure myself if this is something good or completely unnecessary. I just had this idea when working on issue #222. 😉 Also I thought, it would be helpful to document it, regardless if this will be accepted or not.
@gsakkis, @scls19fr What do you think? I would like to hear your opinion. 😉
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (8 by maintainers)
Top Results From Across the Web
Idea: Extend Iterators to break on condition
This idea is based on the need to break an iteration loop when a specific condition is met. As an example, you have...
Read more >Iterator Pattern
Iterator Pattern is a relatively simple and frequently used design pattern. There are a lot of data structures/collections available in every ...
Read more >Are there use cases where you would want to implement ...
Are there use cases where you would want to implement an iterator yourself? Here are some reasons I can think of for implementing...
Read more >itertools — Functions creating iterators for efficient looping
This module implements a number of iterator building blocks inspired by constructs from APL, Haskell, and SML. Each has been recast in a...
Read more >Idea: Fallible iterator mapping with `try_map`
I've come across a use case where I'm looking for a fallible version of the Map iterator, much like the version specified for...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I kinda like the general idea and had also thought of something similar. Two comments for the specific API:
steps
is unnecessary, this can (and should in my opinion) be an infinite iterator. The caller can always useitertools.islice
or others to limit/filter the iterable.part
than the initial one by setting an attribute is not ideal because (a) it is a 2-step process (vit.part = "minor"; next(vit)
) and (b) it is sticky; all subsequentnext
calls will use the new part, although in practice I’d guess it would be more common to bump to minor/major once but continue with the original part for subsequent next versions.Based on these I came up with a simple coroutine approach, where you can
send(part)
for a single next version but preserve the original:Usage:
Not if we want to support arbitrary iterables without expanding them into tuples first.