gallerist 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/CONTRIBUTING.md +53 -0
- data/Gemfile +8 -0
- data/LICENSE +25 -0
- data/README.md +57 -0
- data/Rakefile +16 -0
- data/assets/stylesheets/main.scss +17 -0
- data/bin/gallerist +59 -0
- data/config.ru +21 -0
- data/gallerist.gemspec +32 -0
- data/lib/gallerist.rb +46 -0
- data/lib/gallerist/app.rb +230 -0
- data/lib/gallerist/errors.rb +12 -0
- data/lib/gallerist/helpers.rb +72 -0
- data/lib/gallerist/library.rb +100 -0
- data/lib/gallerist/middleware/raise_warmup_exceptions.rb +24 -0
- data/lib/gallerist/middleware/show_exceptions.rb +40 -0
- data/lib/gallerist/models/admin_data.rb +10 -0
- data/lib/gallerist/models/album.rb +30 -0
- data/lib/gallerist/models/album_photo.rb +20 -0
- data/lib/gallerist/models/base_model.rb +32 -0
- data/lib/gallerist/models/image_proxies_model.rb +11 -0
- data/lib/gallerist/models/image_proxy_state.rb +22 -0
- data/lib/gallerist/models/master.rb +25 -0
- data/lib/gallerist/models/model_resource.rb +22 -0
- data/lib/gallerist/models/person.rb +46 -0
- data/lib/gallerist/models/person_model.rb +10 -0
- data/lib/gallerist/models/person_photo.rb +39 -0
- data/lib/gallerist/models/photo.rb +100 -0
- data/lib/gallerist/models/tag.rb +31 -0
- data/lib/gallerist/models/tag_photo.rb +20 -0
- data/lib/rack/handler/unicorn.rb +34 -0
- data/views/500.erb +5 -0
- data/views/album.erb +9 -0
- data/views/index.erb +24 -0
- data/views/layout.erb +34 -0
- data/views/partials/thumbnail.erb +13 -0
- data/views/person.erb +9 -0
- data/views/photos.erb +9 -0
- data/views/tag.erb +9 -0
- metadata +183 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2015, Sebastian Staudt
|
5
|
+
|
6
|
+
class Gallerist::PersonPhoto < Gallerist::PersonModel
|
7
|
+
|
8
|
+
iphoto do
|
9
|
+
self.table_name = 'RKDetectedFace'
|
10
|
+
|
11
|
+
has_one :person, primary_key: 'faceKey', foreign_key: 'faceKey'
|
12
|
+
|
13
|
+
alias_attribute :master_uuid, :masterUuid
|
14
|
+
alias_attribute :person_id, :faceKey
|
15
|
+
|
16
|
+
def photo
|
17
|
+
Gallerist::Photo.find_by master_uuid: master_uuid
|
18
|
+
end
|
19
|
+
|
20
|
+
def photo_id
|
21
|
+
photo.id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
photos do
|
26
|
+
self.table_name = 'RKPersonVersion'
|
27
|
+
|
28
|
+
has_one :person, primary_key: 'personId', foreign_key: 'modelId'
|
29
|
+
has_one :photo, primary_key: 'versionId', foreign_key: 'modelId'
|
30
|
+
|
31
|
+
alias_attribute :person_id, :personId
|
32
|
+
alias_attribute :photo_id, :versionId
|
33
|
+
end
|
34
|
+
|
35
|
+
def inspect
|
36
|
+
'#<%s person_id=%d photo_id=%s>' % [ self.class, person_id, photo_id ]
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2015, Sebastian Staudt
|
5
|
+
|
6
|
+
class Gallerist::Photo < Gallerist::BaseModel
|
7
|
+
|
8
|
+
self.table_name = 'RKVersion'
|
9
|
+
|
10
|
+
has_one :image_proxy_state, foreign_key: 'versionId'
|
11
|
+
has_one :master, primary_key: 'masterId', foreign_key: 'modelId'
|
12
|
+
has_one :model_resource, -> { where model_type: 2 }, foreign_key: 'attachedModelId'
|
13
|
+
has_many :album_photos, primary_key: 'modelId', foreign_key: 'versionId'
|
14
|
+
has_many :albums, through: :album_photos
|
15
|
+
has_many :tag_photos, primary_key: 'modelId', foreign_key: 'versionId'
|
16
|
+
has_many :tags, -> { distinct }, through: :tag_photos
|
17
|
+
|
18
|
+
iphoto do
|
19
|
+
alias_attribute :master_uuid, :masterUuid
|
20
|
+
|
21
|
+
def person_photos
|
22
|
+
Gallerist::PersonPhoto.where master_uuid: master.uuid
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
photos do
|
27
|
+
has_many :person_photos, primary_key: 'modelId', foreign_key: 'versionId'
|
28
|
+
end
|
29
|
+
|
30
|
+
alias_attribute :date, :imageDate
|
31
|
+
alias_attribute :file_name, :fileName
|
32
|
+
alias_attribute :is_favorite, :isFavorite
|
33
|
+
alias_attribute :show_in_library, :showInLibrary
|
34
|
+
|
35
|
+
delegate :thumbnail_available?, to: :image_proxy_state, allow_nil: true
|
36
|
+
|
37
|
+
scope :favorites, -> { where(is_favorite: true) }
|
38
|
+
|
39
|
+
photos do
|
40
|
+
default_scope do
|
41
|
+
select(:masterId, :modelId, :fileName, :imageDate, :type, :uuid).
|
42
|
+
where(show_in_library: true)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
iphoto do
|
47
|
+
default_scope do
|
48
|
+
select(:masterId, :modelId, :fileName, :imageDate, :uuid).
|
49
|
+
where(show_in_library: true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def image_path
|
54
|
+
if model_resource && !video?
|
55
|
+
uuid = model_resource.uuid
|
56
|
+
first, second = uuid[0].ord.to_s, uuid[1].ord.to_s
|
57
|
+
|
58
|
+
File.join 'resources', 'modelresources', first, second, uuid, model_resource.file_name
|
59
|
+
else
|
60
|
+
File.join 'Masters', master.path
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def inspect
|
65
|
+
"#<%s id=%d uuid=%s file_name='%s'>" % [ self.class, id, uuid, file_name ]
|
66
|
+
end
|
67
|
+
|
68
|
+
def path
|
69
|
+
File.dirname master.path
|
70
|
+
end
|
71
|
+
|
72
|
+
# ActiveRecord does not support has_many-through associations across
|
73
|
+
# different databases, so we have to query the persons manually
|
74
|
+
photos do
|
75
|
+
def persons
|
76
|
+
Gallerist::Person.where modelId: person_photos.map(&:person_id)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
iphoto do
|
81
|
+
def persons
|
82
|
+
Gallerist::Person.where faceKey: person_photos.map(&:person_id)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def preview_path
|
87
|
+
dir_name = File.dirname master.path
|
88
|
+
image_name = File.basename(master.path, '.*') + '.jpg'
|
89
|
+
File.join 'Previews', dir_name, image_name
|
90
|
+
end
|
91
|
+
|
92
|
+
def small_thumbnail_path
|
93
|
+
File.join 'Thumbnails', image_proxy_state.small_thumbnail_path
|
94
|
+
end
|
95
|
+
|
96
|
+
def video?
|
97
|
+
type == 8
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2015, Sebastian Staudt
|
5
|
+
|
6
|
+
class Gallerist::Tag < Gallerist::BaseModel
|
7
|
+
|
8
|
+
self.table_name = 'RKKeyword'
|
9
|
+
|
10
|
+
has_many :tag_photos, primary_key: 'modelId', foreign_key: 'keywordId'
|
11
|
+
has_many :photos, -> { distinct }, through: :tag_photos
|
12
|
+
|
13
|
+
alias_attribute :simple_name, :searchName
|
14
|
+
|
15
|
+
default_scope { select(:modelId, :name, :searchName) }
|
16
|
+
scope :nonempty, -> {
|
17
|
+
joins(:tag_photos).
|
18
|
+
select('count(RKKeywordForVersion.keywordId) as photos_count').
|
19
|
+
group('RKKeywordForVersion.keywordId').
|
20
|
+
having('photos_count > 0')
|
21
|
+
}
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
"#<%s id=%d name='%s'>" % [ self.class, id, name ]
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
name
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2015, Sebastian Staudt
|
5
|
+
|
6
|
+
class Gallerist::TagPhoto < Gallerist::BaseModel
|
7
|
+
|
8
|
+
self.table_name = 'RKKeywordForVersion'
|
9
|
+
|
10
|
+
has_one :tag, primary_key: 'keywordId', foreign_key: 'modelId'
|
11
|
+
has_one :photo, primary_key: 'versionId', foreign_key: 'modelId'
|
12
|
+
|
13
|
+
alias_attribute :tag_id, :keywordId
|
14
|
+
alias_attribute :photo_id, :versionId
|
15
|
+
|
16
|
+
def inspect
|
17
|
+
'#<%s tag_id=%d photo_id=%d>' % [ self.class, tag_id, photo_id ]
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2015, Sebastian Staudt
|
5
|
+
|
6
|
+
require 'unicorn'
|
7
|
+
|
8
|
+
module Rack::Handler::Unicorn
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def run(app, options = {})
|
13
|
+
environment = ENV['RACK_ENV'] || 'development'
|
14
|
+
default_host = (environment == 'development') ? 'localhost' : '0.0.0.0'
|
15
|
+
options[:Host] ||= default_host
|
16
|
+
|
17
|
+
unicorn_options = {
|
18
|
+
listeners: [ '%s:%d' % [ options[:Host], options[:Port] ] ],
|
19
|
+
worker_processes: options[:worker_processes] || 1
|
20
|
+
}
|
21
|
+
|
22
|
+
::Unicorn::Launcher.daemonize!(unicorn_options) if options[:daemonize]
|
23
|
+
::Unicorn::HttpServer.new(app, unicorn_options).start.join
|
24
|
+
end
|
25
|
+
|
26
|
+
def environment
|
27
|
+
ENV['RACK_ENV']
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
Rack::Handler.register :unicorn, Rack::Handler::Unicorn
|
data/views/500.erb
ADDED
data/views/album.erb
ADDED
data/views/index.erb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
<div class="list-group">
|
2
|
+
<a class="list-group-item" href="/photos">All photos</a>
|
3
|
+
<a class="list-group-item" href="/favorites">Favorites</a>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<h2>Albums</h2>
|
7
|
+
|
8
|
+
<div class="list-group">
|
9
|
+
<% @albums.each do |album| %>
|
10
|
+
<%= link_to album, 'list-group-item' %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<h2>Tags</h2>
|
15
|
+
|
16
|
+
<h3>
|
17
|
+
<%= @tags.map { |tag| link_to tag }.join %>
|
18
|
+
</h3>
|
19
|
+
|
20
|
+
<h2>Persons</h2>
|
21
|
+
|
22
|
+
<h3>
|
23
|
+
<%= @persons.map { |person| link_to person }.join %>
|
24
|
+
</h3>
|
data/views/layout.erb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<title><%= title %></title>
|
5
|
+
|
6
|
+
<link href="<%= stylesheet_path 'main' %>" rel="stylesheet">
|
7
|
+
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
<nav class="navbar navbar-default navbar-inverse navbar-static-top">
|
12
|
+
<div class="container-fluid">
|
13
|
+
<div class="navbar-header">
|
14
|
+
<span class="navbar-brand"><strong>Gallerist</strong></span>
|
15
|
+
</div>
|
16
|
+
<ul class="nav navbar-nav">
|
17
|
+
<% (navbar || []).each_with_index do |item, idx| %>
|
18
|
+
<li<%= ' class="active"' if idx == navbar.size - 1 %>>
|
19
|
+
<% if route_exists item.first %>
|
20
|
+
<a href="<%= item.first %>" ><%= item.last %></a>
|
21
|
+
<% else %>
|
22
|
+
<span class="navbar-text"><%= item.last %></span>
|
23
|
+
<% end %>
|
24
|
+
</li>
|
25
|
+
<% end %>
|
26
|
+
</ul>
|
27
|
+
</div>
|
28
|
+
</nav>
|
29
|
+
|
30
|
+
<div class="container-fluid">
|
31
|
+
<%= yield %>
|
32
|
+
</div>
|
33
|
+
</body>
|
34
|
+
</html>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="thumbnail">
|
2
|
+
<a href="<%= url_for(photo) %>">
|
3
|
+
<img src="/thumbs/<%= photo.id %>">
|
4
|
+
</a>
|
5
|
+
<div class="caption">
|
6
|
+
<% unless photo.tags.to_a.empty? %>
|
7
|
+
<p>Tags: <%= photo.tags.map { |t| link_to t }.join('') %></p>
|
8
|
+
<% end %>
|
9
|
+
<% unless photo.persons.to_a.empty? %>
|
10
|
+
<p>Persons: <%= photo.persons.map { |t| link_to t }.join('') %></p>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
</div>
|
data/views/person.erb
ADDED
data/views/photos.erb
ADDED
data/views/tag.erb
ADDED
metadata
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gallerist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sebastian Staudt
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bootstrap-sass
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sinatra
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sprockets-helpers
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: unicorn
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '4.8'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '4.8'
|
111
|
+
description: View Photos and iPhoto libraries in your browser
|
112
|
+
email:
|
113
|
+
- koraktor@gmail.com
|
114
|
+
executables:
|
115
|
+
- gallerist
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- .gitignore
|
120
|
+
- CONTRIBUTING.md
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- assets/stylesheets/main.scss
|
126
|
+
- bin/gallerist
|
127
|
+
- config.ru
|
128
|
+
- gallerist.gemspec
|
129
|
+
- lib/gallerist.rb
|
130
|
+
- lib/gallerist/app.rb
|
131
|
+
- lib/gallerist/errors.rb
|
132
|
+
- lib/gallerist/helpers.rb
|
133
|
+
- lib/gallerist/library.rb
|
134
|
+
- lib/gallerist/middleware/raise_warmup_exceptions.rb
|
135
|
+
- lib/gallerist/middleware/show_exceptions.rb
|
136
|
+
- lib/gallerist/models/admin_data.rb
|
137
|
+
- lib/gallerist/models/album.rb
|
138
|
+
- lib/gallerist/models/album_photo.rb
|
139
|
+
- lib/gallerist/models/base_model.rb
|
140
|
+
- lib/gallerist/models/image_proxies_model.rb
|
141
|
+
- lib/gallerist/models/image_proxy_state.rb
|
142
|
+
- lib/gallerist/models/master.rb
|
143
|
+
- lib/gallerist/models/model_resource.rb
|
144
|
+
- lib/gallerist/models/person.rb
|
145
|
+
- lib/gallerist/models/person_model.rb
|
146
|
+
- lib/gallerist/models/person_photo.rb
|
147
|
+
- lib/gallerist/models/photo.rb
|
148
|
+
- lib/gallerist/models/tag.rb
|
149
|
+
- lib/gallerist/models/tag_photo.rb
|
150
|
+
- lib/rack/handler/unicorn.rb
|
151
|
+
- views/500.erb
|
152
|
+
- views/album.erb
|
153
|
+
- views/index.erb
|
154
|
+
- views/layout.erb
|
155
|
+
- views/partials/thumbnail.erb
|
156
|
+
- views/person.erb
|
157
|
+
- views/photos.erb
|
158
|
+
- views/tag.erb
|
159
|
+
homepage: https://github.com/koraktor/gallerist
|
160
|
+
licenses:
|
161
|
+
- BSD
|
162
|
+
metadata: {}
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - '>='
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
requirements: []
|
178
|
+
rubyforge_project:
|
179
|
+
rubygems_version: 2.4.6
|
180
|
+
signing_key:
|
181
|
+
specification_version: 4
|
182
|
+
summary: A web application to browse Apple Photos and iPhoto libraries
|
183
|
+
test_files: []
|