@@ -738,6 +738,10 @@ Options:
|
|||||||
or 12:00:00.
|
or 12:00:00.
|
||||||
--to-time TIME Search by item end time of day, e.g. 12:00 or
|
--to-time TIME Search by item end time of day, e.g. 12:00 or
|
||||||
12:00:00.
|
12:00:00.
|
||||||
|
--year INTEGER Search for items from a specific year, e.g.
|
||||||
|
--year 2022 to find all photos from the year
|
||||||
|
2022. May be repeated to search multiple
|
||||||
|
years.
|
||||||
--has-comment Search for photos that have comments.
|
--has-comment Search for photos that have comments.
|
||||||
--no-comment Search for photos with no comments.
|
--no-comment Search for photos with no comments.
|
||||||
--has-likes Search for photos that have likes.
|
--has-likes Search for photos that have likes.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>osxphotos.photosdb.photosdb — osxphotos 0.47.5 documentation</title>
|
<title>osxphotos.photosdb.photosdb — osxphotos 0.47.8 documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
||||||
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
||||||
@@ -3322,6 +3322,9 @@
|
|||||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">:</span>
|
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">:</span>
|
||||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o"><=</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">]</span>
|
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o"><=</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">]</span>
|
||||||
|
|
||||||
|
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">year</span><span class="p">:</span>
|
||||||
|
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">year</span> <span class="ow">in</span> <span class="n">options</span><span class="o">.</span><span class="n">year</span><span class="p">]</span>
|
||||||
|
|
||||||
<span class="k">if</span> <span class="n">name</span><span class="p">:</span>
|
<span class="k">if</span> <span class="n">name</span><span class="p">:</span>
|
||||||
<span class="c1"># search filename fields for text</span>
|
<span class="c1"># search filename fields for text</span>
|
||||||
<span class="c1"># if more than one, find photos with all title values in filename</span>
|
<span class="c1"># if more than one, find photos with all title values in filename</span>
|
||||||
|
|||||||
@@ -368,6 +368,13 @@ def QUERY_OPTIONS(f):
|
|||||||
help="Search by item end time of day, e.g. 12:00 or 12:00:00.",
|
help="Search by item end time of day, e.g. 12:00 or 12:00:00.",
|
||||||
type=TimeISO8601(),
|
type=TimeISO8601(),
|
||||||
),
|
),
|
||||||
|
o(
|
||||||
|
"--year",
|
||||||
|
help="Search for items from a specific year, e.g. --year 2022 to find all photos from the year 2022. "
|
||||||
|
"May be repeated to search multiple years.",
|
||||||
|
multiple=True,
|
||||||
|
type=int,
|
||||||
|
),
|
||||||
o("--has-comment", is_flag=True, help="Search for photos that have comments."),
|
o("--has-comment", is_flag=True, help="Search for photos that have comments."),
|
||||||
o("--no-comment", is_flag=True, help="Search for photos with no comments."),
|
o("--no-comment", is_flag=True, help="Search for photos with no comments."),
|
||||||
o("--has-likes", is_flag=True, help="Search for photos that have likes."),
|
o("--has-likes", is_flag=True, help="Search for photos that have likes."),
|
||||||
|
|||||||
@@ -697,6 +697,7 @@ def export(
|
|||||||
to_date,
|
to_date,
|
||||||
from_time,
|
from_time,
|
||||||
to_time,
|
to_time,
|
||||||
|
year,
|
||||||
verbose,
|
verbose,
|
||||||
timestamp,
|
timestamp,
|
||||||
no_progress,
|
no_progress,
|
||||||
@@ -1018,6 +1019,7 @@ def export(
|
|||||||
uuid_from_file = cfg.uuid_from_file
|
uuid_from_file = cfg.uuid_from_file
|
||||||
verbose = cfg.verbose
|
verbose = cfg.verbose
|
||||||
xattr_template = cfg.xattr_template
|
xattr_template = cfg.xattr_template
|
||||||
|
year = cfg.year
|
||||||
|
|
||||||
# config file might have changed verbose
|
# config file might have changed verbose
|
||||||
color_theme = get_theme(theme)
|
color_theme = get_theme(theme)
|
||||||
@@ -1300,6 +1302,7 @@ def export(
|
|||||||
to_date=to_date,
|
to_date=to_date,
|
||||||
from_time=from_time,
|
from_time=from_time,
|
||||||
to_time=to_time,
|
to_time=to_time,
|
||||||
|
year=year,
|
||||||
portrait=portrait,
|
portrait=portrait,
|
||||||
not_portrait=not_portrait,
|
not_portrait=not_portrait,
|
||||||
screenshot=screenshot,
|
screenshot=screenshot,
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ def query(
|
|||||||
to_date,
|
to_date,
|
||||||
from_time,
|
from_time,
|
||||||
to_time,
|
to_time,
|
||||||
|
year,
|
||||||
portrait,
|
portrait,
|
||||||
not_portrait,
|
not_portrait,
|
||||||
screenshot,
|
screenshot,
|
||||||
@@ -174,6 +175,7 @@ def query(
|
|||||||
to_date,
|
to_date,
|
||||||
from_time,
|
from_time,
|
||||||
to_time,
|
to_time,
|
||||||
|
year,
|
||||||
label,
|
label,
|
||||||
is_reference,
|
is_reference,
|
||||||
query_eval,
|
query_eval,
|
||||||
@@ -280,6 +282,7 @@ def query(
|
|||||||
to_date=to_date,
|
to_date=to_date,
|
||||||
from_time=from_time,
|
from_time=from_time,
|
||||||
to_time=to_time,
|
to_time=to_time,
|
||||||
|
year=year,
|
||||||
portrait=portrait,
|
portrait=portrait,
|
||||||
not_portrait=not_portrait,
|
not_portrait=not_portrait,
|
||||||
screenshot=screenshot,
|
screenshot=screenshot,
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ def _query_options_from_kwargs(**kwargs) -> QueryOptions:
|
|||||||
"to_date",
|
"to_date",
|
||||||
"from_time",
|
"from_time",
|
||||||
"to_time",
|
"to_time",
|
||||||
|
"year",
|
||||||
"label",
|
"label",
|
||||||
"is_reference",
|
"is_reference",
|
||||||
"query_eval",
|
"query_eval",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>osxphotos.photosdb.photosdb — osxphotos 0.47.5 documentation</title>
|
<title>osxphotos.photosdb.photosdb — osxphotos 0.47.8 documentation</title>
|
||||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
||||||
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
||||||
@@ -3322,6 +3322,9 @@
|
|||||||
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">:</span>
|
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">:</span>
|
||||||
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o"><=</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">]</span>
|
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o"><=</span> <span class="n">options</span><span class="o">.</span><span class="n">to_time</span><span class="p">]</span>
|
||||||
|
|
||||||
|
<span class="k">if</span> <span class="n">options</span><span class="o">.</span><span class="n">year</span><span class="p">:</span>
|
||||||
|
<span class="n">photos</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">photos</span> <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">year</span> <span class="ow">in</span> <span class="n">options</span><span class="o">.</span><span class="n">year</span><span class="p">]</span>
|
||||||
|
|
||||||
<span class="k">if</span> <span class="n">name</span><span class="p">:</span>
|
<span class="k">if</span> <span class="n">name</span><span class="p">:</span>
|
||||||
<span class="c1"># search filename fields for text</span>
|
<span class="c1"># search filename fields for text</span>
|
||||||
<span class="c1"># if more than one, find photos with all title values in filename</span>
|
<span class="c1"># if more than one, find photos with all title values in filename</span>
|
||||||
|
|||||||
@@ -3289,6 +3289,9 @@ class PhotosDB:
|
|||||||
if options.to_time:
|
if options.to_time:
|
||||||
photos = [p for p in photos if p.date.time() <= options.to_time]
|
photos = [p for p in photos if p.date.time() <= options.to_time]
|
||||||
|
|
||||||
|
if options.year:
|
||||||
|
photos = [p for p in photos if p.date.year in options.year]
|
||||||
|
|
||||||
if name:
|
if name:
|
||||||
# search filename fields for text
|
# search filename fields for text
|
||||||
# if more than one, find photos with all title values in filename
|
# if more than one, find photos with all title values in filename
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ class QueryOptions:
|
|||||||
function: Optional[List[Tuple[callable, str]]] = None
|
function: Optional[List[Tuple[callable, str]]] = None
|
||||||
selected: Optional[bool] = None
|
selected: Optional[bool] = None
|
||||||
exif: Optional[Iterable[Tuple[str, str]]] = None
|
exif: Optional[Iterable[Tuple[str, str]]] = None
|
||||||
|
year: Optional[int] = None
|
||||||
|
|
||||||
def asdict(self):
|
def asdict(self):
|
||||||
return asdict(self)
|
return asdict(self)
|
||||||
|
|||||||
@@ -740,6 +740,8 @@ CLI_FINDER_TAGS = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLI_EXPORT_YEAR_2017 = ["IMG_4547.jpg"]
|
||||||
|
|
||||||
LABELS_JSON = {
|
LABELS_JSON = {
|
||||||
"labels": {
|
"labels": {
|
||||||
"Water": 2,
|
"Water": 2,
|
||||||
@@ -1494,6 +1496,28 @@ def test_export_skip_uuid():
|
|||||||
assert skipped_file not in files
|
assert skipped_file not in files
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_year():
|
||||||
|
"""test export with --year"""
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
# pylint: disable=not-context-manager
|
||||||
|
with runner.isolated_filesystem():
|
||||||
|
result = runner.invoke(
|
||||||
|
export,
|
||||||
|
[
|
||||||
|
os.path.join(cwd, CLI_PHOTOS_DB),
|
||||||
|
".",
|
||||||
|
"-V",
|
||||||
|
"--year",
|
||||||
|
"2017",
|
||||||
|
"--skip-edited",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
files = glob.glob("*")
|
||||||
|
assert sorted(files) == sorted(CLI_EXPORT_YEAR_2017)
|
||||||
|
|
||||||
|
|
||||||
def test_export_preview():
|
def test_export_preview():
|
||||||
"""test export with --preview"""
|
"""test export with --preview"""
|
||||||
|
|
||||||
@@ -2572,6 +2596,80 @@ def test_query_time():
|
|||||||
assert len(json_got) == 3
|
assert len(json_got) == 3
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_year_1():
|
||||||
|
"""Test --year"""
|
||||||
|
|
||||||
|
os.environ["TZ"] = "US/Pacific"
|
||||||
|
time.tzset()
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
result = runner.invoke(
|
||||||
|
query,
|
||||||
|
[
|
||||||
|
"--json",
|
||||||
|
"--db",
|
||||||
|
os.path.join(cwd, CLI_PHOTOS_DB),
|
||||||
|
"--year",
|
||||||
|
2017,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
|
||||||
|
json_got = json.loads(result.output)
|
||||||
|
assert len(json_got) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_year_2():
|
||||||
|
"""Test --year with multiple years"""
|
||||||
|
|
||||||
|
os.environ["TZ"] = "US/Pacific"
|
||||||
|
time.tzset()
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
result = runner.invoke(
|
||||||
|
query,
|
||||||
|
[
|
||||||
|
"--json",
|
||||||
|
"--db",
|
||||||
|
os.path.join(cwd, CLI_PHOTOS_DB),
|
||||||
|
"--year",
|
||||||
|
2017,
|
||||||
|
"--year",
|
||||||
|
2018,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
|
||||||
|
json_got = json.loads(result.output)
|
||||||
|
assert len(json_got) == 6
|
||||||
|
|
||||||
|
|
||||||
|
def test_query_year_3():
|
||||||
|
"""Test --year with invalid year"""
|
||||||
|
|
||||||
|
os.environ["TZ"] = "US/Pacific"
|
||||||
|
time.tzset()
|
||||||
|
|
||||||
|
runner = CliRunner()
|
||||||
|
cwd = os.getcwd()
|
||||||
|
result = runner.invoke(
|
||||||
|
query,
|
||||||
|
[
|
||||||
|
"--json",
|
||||||
|
"--db",
|
||||||
|
os.path.join(cwd, CLI_PHOTOS_DB),
|
||||||
|
"--year",
|
||||||
|
3000,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
assert result.exit_code == 0
|
||||||
|
|
||||||
|
json_got = json.loads(result.output)
|
||||||
|
assert len(json_got) == 0
|
||||||
|
|
||||||
|
|
||||||
def test_query_keyword_1():
|
def test_query_keyword_1():
|
||||||
"""Test query --keyword"""
|
"""Test query --keyword"""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user