arduino-library 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.travis.yml +19 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +233 -0
- data/Rakefile +6 -0
- data/arduino-library.gemspec +33 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/arduino/library.rb +55 -0
- data/lib/arduino/library/database.rb +82 -0
- data/lib/arduino/library/model.rb +104 -0
- data/lib/arduino/library/presenters/properties.rb +63 -0
- data/lib/arduino/library/types.rb +109 -0
- data/lib/arduino/library/utilities.rb +19 -0
- data/lib/arduino/library/version.rb +8 -0
- metadata +179 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2d37473a87d3b6d1db40f35624c2c797529da16c
|
4
|
+
data.tar.gz: 3c8df8283d9c010ef9602ce81e93d892bb7bfcac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2c2f9b036d4cd3bd906456ec6fcb1282545eedfc93d4de06ad49938cc2f5d78e6f6b07aad1b769d1e7575ad13a9b370a7e85dad46d1ae8b1561ac0e5c033fa56
|
7
|
+
data.tar.gz: 46a370bc44c4e21a15a12d90ddbd6c50e6104843a65b68b7d79d9810576347aee88540dc0824e0856724540b29fffbff6f5bff49f211fb873f6e0b704dadc35c
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
sudo: false
|
2
|
+
env:
|
3
|
+
global:
|
4
|
+
- CI=TRAVIS
|
5
|
+
- CC_TEST_REPORTER_ID=0e339f5c9d1bbcceab27065342b2e22535bb469bd083a6f44ddb8a262f71f8a4
|
6
|
+
language: ruby
|
7
|
+
rvm:
|
8
|
+
- 2.4.2
|
9
|
+
- 2.3.5
|
10
|
+
before_install:
|
11
|
+
- gem install bundler -v 1.15.4
|
12
|
+
before_script:
|
13
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
14
|
+
- chmod +x ./cc-test-reporter
|
15
|
+
- ./cc-test-reporter before-build
|
16
|
+
script:
|
17
|
+
- bundle exec rspec --format documentation
|
18
|
+
after_script:
|
19
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Konstantin Gredeskoul
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,233 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/arduino-library.svg)](https://badge.fury.io/rb/arduino-library)
|
2
|
+
[![Build Status](https://travis-ci.org/kigster/arduino-library.svg?branch=master)](https://travis-ci.org/kigster/arduino-library)
|
3
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/0da01eba1b556826a231/maintainability)](https://codeclimate.com/github/kigster/arduino-library/maintainability)
|
4
|
+
[![Downloads](http://ruby-gem-downloads-badge.herokuapp.com/arduino-library?type=total)](https://rubygems.org/gems/arduino-library)
|
5
|
+
|
6
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/0da01eba1b556826a231/test_coverage)](https://codeclimate.com/github/kigster/arduino-library/test_coverage)
|
7
|
+
[![Test Coverage](https://codeclimate.com/github/kigster/arduino-library/badges/coverage.svg)](https://codeclimate.com/github/kigster/arduino-library/coverage)
|
8
|
+
|
9
|
+
# Arduino::Library
|
10
|
+
|
11
|
+
This gem encapsulates various rules about the [`library.properties`](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#library-metadata) file that contains meta-data about Arduino Libraries.
|
12
|
+
|
13
|
+
It also provides convenient shortcuts for downloading the Arduino-maintained database of published libraries in JSON format, searching for various libraries, choosing a version, and more.
|
14
|
+
|
15
|
+
It also provides validation functionality for the `library.properties` file for your custom libraries you would like to open source.
|
16
|
+
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem 'arduino-library'
|
24
|
+
```
|
25
|
+
|
26
|
+
And then execute:
|
27
|
+
|
28
|
+
$ bundle
|
29
|
+
|
30
|
+
Or install it yourself as:
|
31
|
+
|
32
|
+
$ gem install arduino-library
|
33
|
+
|
34
|
+
## Usage
|
35
|
+
|
36
|
+
Current version only contains Ruby-based API and is meant to be consumed by other projects (in particularly, check out [Arli](https://github.com/kigster/arli) — a command-line tool and an Arduino Library Manager and installer). This project is invaluable if you are you using, for example, [arduino-cmake](https://github.com/arduino-cmake/arduino-cmake) project to build and upload your Arduino Code.
|
37
|
+
|
38
|
+
|
39
|
+
### Using the top-level module
|
40
|
+
|
41
|
+
If you prefer not to have hard-coded dependencies on the `Arduino::Library::*` sub-classes and sub-modules, you can use the top level module, which proxies several shortcut methods.
|
42
|
+
|
43
|
+
You can access these methods in two different ways:
|
44
|
+
|
45
|
+
1. As class methods on `Arduino::Library`, for example `Arduino::Library.db_default`
|
46
|
+
2. By including the top-level module in your context, and using methods as instance methods in the current context, eg. `#db_default`
|
47
|
+
|
48
|
+
Below we'll focus on the second usage, but if you prefer to use the first syntax, it's there and available for you.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
require 'arduino/library'
|
52
|
+
include Arduino::Library
|
53
|
+
```
|
54
|
+
|
55
|
+
#### Using `db_from`
|
56
|
+
|
57
|
+
This method returns an instance of the `Arduino::Library::Database` from the provided source:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
db_from('library_index.json').size
|
61
|
+
# => 16
|
62
|
+
db_from('library_index.json.gz').size
|
63
|
+
# => 16
|
64
|
+
db_from('http://downloads.arduino.cc/libraries/library_index.json.gz').size
|
65
|
+
# => 3653
|
66
|
+
# This required downloading a 400K gzipped file into a temp file, and reading from there.
|
67
|
+
```
|
68
|
+
|
69
|
+
#### Using `db_default`
|
70
|
+
|
71
|
+
This method downloads and returns the official Arduino-maintained index of Arduino libraries.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
db_default.size
|
75
|
+
# => 3653
|
76
|
+
```
|
77
|
+
|
78
|
+
#### Using `library_from`
|
79
|
+
|
80
|
+
This method reads from a source that can be of many formats (see below) and returns an instantiated `Arduino::Library::Model` for this library. You can then get all library attributes via corresponding methods:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
library_from('spec/fixtures/audio_zero.json').name
|
84
|
+
# => 'AudioZero'
|
85
|
+
library_from('~/Documents/Arduino/Libraries/AudioZero/library.properties').name
|
86
|
+
#=> 'AudioZero'
|
87
|
+
library_from('https://raw.githubusercontent.com/PaulStoffregen/DS1307RTC/master/library.properties').name
|
88
|
+
#=> 'DS1307RTC'
|
89
|
+
```
|
90
|
+
|
91
|
+
#### Using `find`
|
92
|
+
|
93
|
+
Method `find` is, perhaps, some of the most powerful functionality in this gem. It allows constructing very flexible and precise queries, to match any number of library attributes.
|
94
|
+
|
95
|
+
The method has the following signature:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
find(database = db_default, **opts)
|
99
|
+
```
|
100
|
+
|
101
|
+
`opts` is a Hash that you can use to pass attributes with matchers. All matching results are returned as an array of models.
|
102
|
+
|
103
|
+
**Examples**
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
results = find(
|
107
|
+
name: 'AudioZero',
|
108
|
+
author: /konstantin/i, # regexp supported
|
109
|
+
architectures: [ 'avr' ], # array is matched if it's a subset
|
110
|
+
version: proc do |value| # or a proc for max flexibility
|
111
|
+
value.start_with?('1.')
|
112
|
+
end
|
113
|
+
)
|
114
|
+
|
115
|
+
results.size
|
116
|
+
#=> <whatever number of matches returned>
|
117
|
+
```
|
118
|
+
|
119
|
+
Note that multiple attributes must ALL match for the library to be included in the result set.
|
120
|
+
|
121
|
+
### `Arduino::Library::Database`
|
122
|
+
|
123
|
+
> Downloading the index of all libraries, and finding a library.
|
124
|
+
|
125
|
+
You can load libraries from a local JSON file, or from a remote URL, eg:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
require 'arduino/library'
|
129
|
+
|
130
|
+
database = Arduino::Library::Database.from(
|
131
|
+
'http://downloads.arduino.cc/libraries/library_index.json.gz')
|
132
|
+
```
|
133
|
+
|
134
|
+
or, since the above link happens to be the default location of Arduino-maintained librarie index file, you can use the `default` method instead:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
database = Arduino::Library::Database.default
|
138
|
+
```
|
139
|
+
|
140
|
+
or, load the list from a local JSON file, that can be optionally gzipped (just like the URL):
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
database = Arduino::Library::Database.from('library_index.json.gz')
|
144
|
+
```
|
145
|
+
|
146
|
+
Once the library is initialized, the following operations are supported:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
database.find(name: 'AudioZero', version: '1.0.1') do |audio_zero|
|
150
|
+
audio_zero.website #=> http://arduino.cc/en/Reference/Audio
|
151
|
+
audio_zero.architectures #=> [ 'samd' ]
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
You can pass any of the attributes to #find, and the value can be a `String` (in which case only equality matches), or a regular expression, eg:
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
database.find(author: "Paul Stoffregen").size #=> 21
|
159
|
+
database.find(author: /stoffregen/i).size #=> 33
|
160
|
+
```
|
161
|
+
|
162
|
+
You interate over multiple using either a block:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
database.find(name: 'AudioZero') do |match|
|
166
|
+
puts match.name # => 'AudioZero'
|
167
|
+
puts match.version # => will print all versions of the library available
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
or, just grab the return value from `#find`, which is always an array.
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
all_versions = database.find(name: 'AudioZero')
|
175
|
+
# => [ Arduino::Library::Model<name: AudioZero, version: '1.0.1',... >, .. ]
|
176
|
+
```
|
177
|
+
|
178
|
+
### `Arduino::Library::Model`
|
179
|
+
|
180
|
+
> Use this class to operate on a single library.
|
181
|
+
|
182
|
+
#### Reading Library from an External Source using `.from`
|
183
|
+
|
184
|
+
You can use an intelligent class method `.from` that attempts to auto-detect the type of file or URL you are passing as an argument, and use an appropriate parser for each type.
|
185
|
+
|
186
|
+
For example, to read from a JSON file:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
json_file = 'spec/fixtures/audio_zero.json'
|
190
|
+
model = Arduino::Library::Model.from(json_file)
|
191
|
+
model.name #=> 'AudioZero'
|
192
|
+
```
|
193
|
+
|
194
|
+
Or to read from the `.properties` file:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
properties_file = 'spec/fixtures/audio_zero.properties'
|
198
|
+
model = Arduino::Library::Model.from(properties_file)
|
199
|
+
model.name #=> 'AudioZero'
|
200
|
+
```
|
201
|
+
|
202
|
+
### Presenters
|
203
|
+
|
204
|
+
Presenters are there to convert to and from a particular format.
|
205
|
+
|
206
|
+
#### `.properties` Presenter
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
props = Arduino::Library::Presenters::Properties.new(model).present
|
210
|
+
File.open('/tmp/audio_zero.properties', 'w') do |f|
|
211
|
+
f.write(props)
|
212
|
+
end
|
213
|
+
|
214
|
+
# this creates a file in the format:
|
215
|
+
|
216
|
+
# name=AudioZero
|
217
|
+
# version=1.0.1
|
218
|
+
# etc.
|
219
|
+
```
|
220
|
+
|
221
|
+
## Development
|
222
|
+
|
223
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
224
|
+
|
225
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
226
|
+
|
227
|
+
## Contributing
|
228
|
+
|
229
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/kigster/arduino-library](https://github.com/kigster/arduino-library).
|
230
|
+
|
231
|
+
## License
|
232
|
+
|
233
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'arduino/library/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'arduino-library'
|
8
|
+
spec.version = Arduino::Library::VERSION
|
9
|
+
spec.authors = ['Konstantin Gredeskoul']
|
10
|
+
spec.email = ['kigster@gmail.com']
|
11
|
+
spec.summary = Arduino::Library::DESCRIPTION
|
12
|
+
spec.description = Arduino::Library::DESCRIPTION
|
13
|
+
spec.homepage = 'https://github.com/kigster/arduino-library'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
|
20
|
+
spec.bindir = 'exe'
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_dependency 'dry-configurable'
|
25
|
+
spec.add_dependency 'dry-types'
|
26
|
+
spec.add_dependency 'dry-struct'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'simplecov'
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
30
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
|
+
spec.add_development_dependency 'rspec-its'
|
33
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "arduino/library"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Arduino
|
4
|
+
module Library
|
5
|
+
DEFAULT_ARDUINO_LIBRARY_INDEX_URL = 'http://downloads.arduino.cc/libraries/library_index.json.gz'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'arduino/library/version'
|
10
|
+
require 'arduino/library/utilities'
|
11
|
+
require 'arduino/library/types'
|
12
|
+
# noinspection RubyResolve
|
13
|
+
require 'arduino/library/model'
|
14
|
+
require 'arduino/library/database'
|
15
|
+
|
16
|
+
module Arduino
|
17
|
+
module Library
|
18
|
+
# @param [String] file_or_url — either a local file, or URL, can be gzipped
|
19
|
+
def db_from(file_or_url)
|
20
|
+
Database.new(file_or_url)
|
21
|
+
end
|
22
|
+
|
23
|
+
def db_default
|
24
|
+
Database.default
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# +file_or_url+ can be a JSON file name, a .properties file name, or
|
29
|
+
# a URL to either of the above.
|
30
|
+
#
|
31
|
+
# @param [String] file_or_url
|
32
|
+
def library_from(file_or_url)
|
33
|
+
Arduino::Library::Model.from(file_or_url)
|
34
|
+
end
|
35
|
+
|
36
|
+
# +opts+ is a Hash that you can use to pass attributes with values, any
|
37
|
+
# number of them. All matching results are returned as models.
|
38
|
+
#
|
39
|
+
# name: 'AudioZero'
|
40
|
+
# author: /konstantin/i - regexp supported
|
41
|
+
# architectures: [ 'avr' ] - array is matched if it's a subset
|
42
|
+
# version: proc do |value| — or a proc for max flexibility
|
43
|
+
# value.start_with?('1.') )
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# @param [Hash] opts — hash of attribute names and values to match
|
47
|
+
def find(database = db_default, **opts)
|
48
|
+
Arduino::Library::Model.database = database
|
49
|
+
Arduino::Library::Model.from(nil, **opts)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Arduino::Library.extend(Arduino::Library)
|
55
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'zlib'
|
3
|
+
require 'json'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'arduino/library'
|
6
|
+
require 'arduino/library/model'
|
7
|
+
|
8
|
+
module Arduino
|
9
|
+
module Library
|
10
|
+
|
11
|
+
# This class represents a single entry into the library-index.json file,
|
12
|
+
# in other words — a `library.properties` file.
|
13
|
+
class Database
|
14
|
+
extend Forwardable
|
15
|
+
include Utilities
|
16
|
+
|
17
|
+
def_delegators :@db_list, *(Array.new.methods - Object.methods)
|
18
|
+
|
19
|
+
class << self
|
20
|
+
alias from new
|
21
|
+
|
22
|
+
def default
|
23
|
+
@default ||= new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_accessor :local_file,
|
28
|
+
:db_list
|
29
|
+
|
30
|
+
def initialize(file_or_url = Arduino::Library::DEFAULT_ARDUINO_LIBRARY_INDEX_URL)
|
31
|
+
self.local_file = read_file_or_url(file_or_url)
|
32
|
+
load_json
|
33
|
+
end
|
34
|
+
|
35
|
+
# Usage: find(attr1: value, attr2: /regexp/, ... )
|
36
|
+
def find(**opts)
|
37
|
+
limit = opts[:limit]
|
38
|
+
opts.delete(:limit)
|
39
|
+
match_list = []
|
40
|
+
|
41
|
+
db_list.find do |entry|
|
42
|
+
matches = entry_matches?(entry, opts)
|
43
|
+
match_list << entry if matches
|
44
|
+
break if limit && match_list.size >= limit
|
45
|
+
end
|
46
|
+
|
47
|
+
match_list.each { |entry| yield(entry) } if block_given?
|
48
|
+
match_list
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def entry_matches?(entry, opts)
|
54
|
+
matches = true
|
55
|
+
opts.each_pair do |attr, check|
|
56
|
+
value = entry.send(attr)
|
57
|
+
matches &= case check
|
58
|
+
when String
|
59
|
+
value == check
|
60
|
+
when Regexp
|
61
|
+
value =~ check
|
62
|
+
when Array
|
63
|
+
value = value.split(',') unless value.is_a?(Array)
|
64
|
+
value.eql?(check) || value.include?(check) || value.first == '*'
|
65
|
+
when Proc
|
66
|
+
check.call(value)
|
67
|
+
else
|
68
|
+
raise InvalidArgument, "Class #{check.class.name} is unsupported for value checks"
|
69
|
+
end
|
70
|
+
break unless matches
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def load_json
|
77
|
+
hash = JSON.load(local_file.read)
|
78
|
+
self.db_list = hash['libraries'].map { |lib| Model.from_hash(lib) }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require_relative 'types'
|
2
|
+
require_relative 'utilities'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Arduino
|
6
|
+
module Library
|
7
|
+
# This class represents a single entry into the library-index.json file,
|
8
|
+
# in other words — a `library.properties` file.
|
9
|
+
class Model < Dry::Struct
|
10
|
+
|
11
|
+
# noinspection RubyResolve
|
12
|
+
constructor_type :symbolized
|
13
|
+
|
14
|
+
Types::LIBRARY_PROPERTIES.each_pair do |field, type|
|
15
|
+
self.attribute field, eval(type)
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
include Utilities
|
20
|
+
|
21
|
+
attr_writer :database
|
22
|
+
|
23
|
+
def from_hash(hash)
|
24
|
+
new(Types.schema[hash])
|
25
|
+
end
|
26
|
+
|
27
|
+
def from_json(json)
|
28
|
+
from_hash(JSON.load(json))
|
29
|
+
end
|
30
|
+
|
31
|
+
def from_json_file(file_or_url)
|
32
|
+
file = read_file_or_url(file_or_url)
|
33
|
+
from_json(file.read)
|
34
|
+
end
|
35
|
+
|
36
|
+
def from_properties_file(file_or_url)
|
37
|
+
raise "File #{file_or_url} does not exist?" unless File.exist?(file_or_url)
|
38
|
+
Presenters::Properties.from(file_or_url)
|
39
|
+
end
|
40
|
+
|
41
|
+
def database
|
42
|
+
@database ||= Database.default
|
43
|
+
end
|
44
|
+
|
45
|
+
def find(**opts)
|
46
|
+
database.find(**opts)
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param [Object] source — file name or a URL to JSON or .properties file
|
50
|
+
#
|
51
|
+
# ## Searching
|
52
|
+
#
|
53
|
+
# #### Database
|
54
|
+
#
|
55
|
+
# Searching requires a database, which can either be set via
|
56
|
+
#
|
57
|
+
# Arduino::Library::Model.database = Database.from(file)
|
58
|
+
#
|
59
|
+
# otherwise it defaults to the default database, +Database.default+.
|
60
|
+
#
|
61
|
+
# @param [Hash] opts — search parameters to the current database
|
62
|
+
#
|
63
|
+
# #### Query
|
64
|
+
#
|
65
|
+
# +opts+ is a Hash that you can use to pass attributes with values, any
|
66
|
+
# number of them. All matching results are returned as models from the
|
67
|
+
# current database.
|
68
|
+
#
|
69
|
+
# name: 'AudioZero'
|
70
|
+
# author: /konstantin/i - regexp supported
|
71
|
+
# architectures: [ 'avr' ] - array is matched if it's a subset
|
72
|
+
# version: proc do |value| — or a proc for max flexibility
|
73
|
+
# value.start_with?('1.') )
|
74
|
+
# ends
|
75
|
+
#
|
76
|
+
# @return [Model | Array<Model> ] — array for search, otherwise a model
|
77
|
+
def from(source = nil, **opts)
|
78
|
+
case source
|
79
|
+
when Hash
|
80
|
+
from_hash(source)
|
81
|
+
when String
|
82
|
+
if source =~ /^{/m
|
83
|
+
from_json(source)
|
84
|
+
elsif File.exist?(source)
|
85
|
+
if source =~ /\.json(\.gz)?$/i
|
86
|
+
from_json_file(source)
|
87
|
+
elsif source =~ /\.properties(\.gz)?$/i
|
88
|
+
from_properties_file(source)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
when NilClass
|
92
|
+
if opts && opts[:name] && opts[:version]
|
93
|
+
find(**opts)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
require_relative 'presenters/properties'
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'arduino/library/types'
|
2
|
+
require 'arduino/library/model'
|
3
|
+
|
4
|
+
module Arduino
|
5
|
+
module Library
|
6
|
+
module Presenters
|
7
|
+
class Properties < Struct.new(:model)
|
8
|
+
class << self
|
9
|
+
include ::Arduino::Library::Utilities
|
10
|
+
# Class method, that reads a properties file and returns a properly
|
11
|
+
# validated Arduino::Library::Model instance.
|
12
|
+
def from(file_or_url)
|
13
|
+
file = read_file_or_url(file_or_url)
|
14
|
+
props = file.read.split(/\n/)
|
15
|
+
hash = {}
|
16
|
+
props.each do |line|
|
17
|
+
attr, value = line.split('=')
|
18
|
+
attr = attr.to_sym
|
19
|
+
if Types::ARRAY_ATTRIBUTES.include?(attr)
|
20
|
+
hash[attr] = value.split(',')
|
21
|
+
else
|
22
|
+
hash[attr] = value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
::Arduino::Library::Model.from_hash(hash)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor :presented
|
30
|
+
|
31
|
+
def initialize(*args)
|
32
|
+
super(*args)
|
33
|
+
self.presented = ''
|
34
|
+
end
|
35
|
+
|
36
|
+
# Primary instance method, returns a string representing a
|
37
|
+
# library.properties format file, using the model.
|
38
|
+
# The presented value is cached in the #presented public instance
|
39
|
+
# variable.
|
40
|
+
def present
|
41
|
+
Types::LIBRARY_PROPERTIES.keys.each do |attr|
|
42
|
+
attribute_presenter(attr)
|
43
|
+
end
|
44
|
+
presented
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def attribute_presenter(attr)
|
50
|
+
value = model.send(attr) if model && model.respond_to?(attr)
|
51
|
+
return unless value
|
52
|
+
if value.is_a?(Array)
|
53
|
+
self.presented << "#{attr}=#{model.send(attr).join(',')}\n"
|
54
|
+
else
|
55
|
+
self.presented << "#{attr}=#{model.send(attr)}\n"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'dry-types'
|
2
|
+
require 'dry-struct'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Arduino
|
6
|
+
module Library
|
7
|
+
module Types
|
8
|
+
include Dry::Types.module
|
9
|
+
|
10
|
+
Name = String.constrained format: /^[A-Za-z_.-][A-Za-z0-9 _.-]*[A-Za-z0-9_.-]$/
|
11
|
+
Version = String.constrained format: /[0-9]+\.[0-9]+(\.[0-9]+)?/
|
12
|
+
|
13
|
+
Url = String.constrained format: URI::regexp(%w(http https))
|
14
|
+
|
15
|
+
Category = String.enum('Display',
|
16
|
+
'Signal Input/Output',
|
17
|
+
'Communication',
|
18
|
+
'Sensors',
|
19
|
+
'Device Control',
|
20
|
+
'Timing',
|
21
|
+
'Data Storage',
|
22
|
+
'Data Processing',
|
23
|
+
'Other')
|
24
|
+
|
25
|
+
Architecture = String.enum(
|
26
|
+
'*',
|
27
|
+
'AVR',
|
28
|
+
'ESP8266',
|
29
|
+
'FP51',
|
30
|
+
'OpenBCI 32',
|
31
|
+
'RFduino',
|
32
|
+
'SAM',
|
33
|
+
'SAMD',
|
34
|
+
'STM32F1',
|
35
|
+
'Simblee',
|
36
|
+
'Simula',
|
37
|
+
'all',
|
38
|
+
'ameba',
|
39
|
+
'arc32',
|
40
|
+
'arm',
|
41
|
+
'atmelavr',
|
42
|
+
'avr',
|
43
|
+
'esp32',
|
44
|
+
'esp8266',
|
45
|
+
'nRF5',
|
46
|
+
'nRF51822',
|
47
|
+
'nRF52832',
|
48
|
+
'nrf52',
|
49
|
+
'pic32',
|
50
|
+
'rtl8195a',
|
51
|
+
'sam',
|
52
|
+
'samd',
|
53
|
+
'simblee',
|
54
|
+
'stm32',
|
55
|
+
'stm32f4',
|
56
|
+
'teensy',
|
57
|
+
'tiny')
|
58
|
+
|
59
|
+
LibraryTypes = String.enum(
|
60
|
+
'Arduino',
|
61
|
+
'Contributed',
|
62
|
+
'Partner',
|
63
|
+
'Recommended',
|
64
|
+
'Retired'
|
65
|
+
)
|
66
|
+
|
67
|
+
FileName = String.constrained(
|
68
|
+
format: /[a-zA-Z0-9_=.:]+/
|
69
|
+
)
|
70
|
+
|
71
|
+
Checksum = String.constrained(
|
72
|
+
format: /SHA-256:[0-9a-fA-F]{64}/
|
73
|
+
)
|
74
|
+
|
75
|
+
StringField = Coercible::String
|
76
|
+
|
77
|
+
LIBRARY_PROPERTIES = {
|
78
|
+
name: 'Types::String',
|
79
|
+
version: 'Types::String',
|
80
|
+
author: 'Types::String',
|
81
|
+
maintainer: 'Types::String',
|
82
|
+
sentence: 'Types::String',
|
83
|
+
paragraph: 'Types::String',
|
84
|
+
website: 'Types::Url',
|
85
|
+
category: 'Types::Category',
|
86
|
+
architectures: 'Types::Json::Array.member(Types::Architecture)',
|
87
|
+
types: 'Types::Json::Array.member(Types::LibraryTypes)',
|
88
|
+
url: 'Types::Url',
|
89
|
+
archiveFileName: 'Types::FileName',
|
90
|
+
size: 'Types::Coercible::Int',
|
91
|
+
checksum: 'Types::Checksum',
|
92
|
+
dot_a_linkage: 'Types::Bool.optional',
|
93
|
+
includes: 'Types::Json::Array.member(Types::FileName).optional',
|
94
|
+
}.freeze
|
95
|
+
|
96
|
+
ARRAY_ATTRIBUTES = LIBRARY_PROPERTIES.keys.select { |k| LIBRARY_PROPERTIES[k] =~ /Array/ }
|
97
|
+
|
98
|
+
class << self
|
99
|
+
attr_accessor :schema
|
100
|
+
end
|
101
|
+
|
102
|
+
# Let's keep the original hash intact; otherwise dry-struct munges it.
|
103
|
+
hash = LIBRARY_PROPERTIES.dup
|
104
|
+
hash.each { |attribute, type| hash[attribute] = eval(type) }
|
105
|
+
|
106
|
+
self.schema = Types::Hash.symbolized(hash)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Arduino
|
4
|
+
module Library
|
5
|
+
|
6
|
+
module Utilities
|
7
|
+
def read_file_or_url(file_or_url)
|
8
|
+
raise ArgumentError, 'Empty file_or_url provided' unless file_or_url
|
9
|
+
temp_file = open(file_or_url)
|
10
|
+
if file_or_url =~ /\.gz$/i
|
11
|
+
Zlib::GzipReader.new(temp_file)
|
12
|
+
else
|
13
|
+
temp_file
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Arduino
|
2
|
+
module Library
|
3
|
+
VERSION = '0.3.0'
|
4
|
+
DESCRIPTION = <<-eof
|
5
|
+
This gem encapsulates many concepts related to how Arduino Libraries are indexed, how their metadata is validated, or .properties file generated. It supports searching the Arduino library database for any terms. This gem is used by Arli — Arduino Installer CLI toolkit.
|
6
|
+
eof
|
7
|
+
end
|
8
|
+
end
|
metadata
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: arduino-library
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Konstantin Gredeskoul
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-configurable
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-types
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-struct
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.15'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.15'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec-its
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: " This gem encapsulates many concepts related to how Arduino Libraries
|
126
|
+
are indexed, how their metadata is validated, or .properties file generated. It
|
127
|
+
supports searching the Arduino library database for any terms. This gem is used
|
128
|
+
by Arli — Arduino Installer CLI toolkit.\n"
|
129
|
+
email:
|
130
|
+
- kigster@gmail.com
|
131
|
+
executables: []
|
132
|
+
extensions: []
|
133
|
+
extra_rdoc_files: []
|
134
|
+
files:
|
135
|
+
- ".gitignore"
|
136
|
+
- ".rspec"
|
137
|
+
- ".travis.yml"
|
138
|
+
- Gemfile
|
139
|
+
- LICENSE.txt
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- arduino-library.gemspec
|
143
|
+
- bin/console
|
144
|
+
- bin/setup
|
145
|
+
- lib/arduino/library.rb
|
146
|
+
- lib/arduino/library/database.rb
|
147
|
+
- lib/arduino/library/model.rb
|
148
|
+
- lib/arduino/library/presenters/properties.rb
|
149
|
+
- lib/arduino/library/types.rb
|
150
|
+
- lib/arduino/library/utilities.rb
|
151
|
+
- lib/arduino/library/version.rb
|
152
|
+
homepage: https://github.com/kigster/arduino-library
|
153
|
+
licenses:
|
154
|
+
- MIT
|
155
|
+
metadata: {}
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 2.6.11
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: This gem encapsulates many concepts related to how Arduino Libraries are
|
176
|
+
indexed, how their metadata is validated, or .properties file generated. It supports
|
177
|
+
searching the Arduino library database for any terms. This gem is used by Arli —
|
178
|
+
Arduino Installer CLI toolkit.
|
179
|
+
test_files: []
|