wgit 0.10.8 → 0.12.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 +4 -4
- data/CHANGELOG.md +72 -1
- data/CODE_OF_CONDUCT.md +1 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +24 -20
- data/bin/wgit +75 -19
- data/lib/wgit/assertable.rb +33 -6
- data/lib/wgit/core_ext.rb +1 -1
- data/lib/wgit/crawler.rb +102 -37
- data/lib/wgit/database/adapters/in_memory.rb +204 -0
- data/lib/wgit/database/adapters/mongo_db.rb +627 -0
- data/lib/wgit/database/database.rb +18 -651
- data/lib/wgit/database/database_adapter.rb +147 -0
- data/lib/wgit/document.rb +222 -98
- data/lib/wgit/document_extractors.rb +16 -10
- data/lib/wgit/dsl.rb +74 -81
- data/lib/wgit/html_to_text.rb +277 -0
- data/lib/wgit/indexer.rb +184 -71
- data/lib/wgit/logger.rb +2 -2
- data/lib/wgit/model.rb +164 -0
- data/lib/wgit/response.rb +25 -13
- data/lib/wgit/robots_parser.rb +193 -0
- data/lib/wgit/url.rb +150 -90
- data/lib/wgit/utils.rb +200 -37
- data/lib/wgit/version.rb +1 -1
- data/lib/wgit.rb +18 -13
- metadata +56 -43
- data/lib/wgit/database/model.rb +0 -60
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4dee43af6274102c9bc6ad4f32c8811f57c5dc2833e923e038aac8f7f2072385
|
|
4
|
+
data.tar.gz: 9463768a40c78ab9c91ac34dd1c3a0fd1e7b990440b70766feebb9e2f0f99bd4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c94fcae3a56254a6c0d9d67597f1a2125439c1ee3d7d68e22fb70fa59298735d76b0fb8e77bc44b0850f6ba561fe11df3a867973d5f0533adddda9d2c6f2002
|
|
7
|
+
data.tar.gz: 779bf20dc1eaa29cc926a836d5a5a155c2270db1be0d22bc52ba9893cbd8d3aaec2cee7810b660fb9014020f5de2290af2b23680cc040a9c682ca82431d6f50d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Wgit Change Log
|
|
2
2
|
|
|
3
|
-
## v0.0.0 (TEMPLATE - DO NOT EDIT)
|
|
3
|
+
## v0.0.0 [- BREAKING CHANGES] (TEMPLATE - DO NOT EDIT)
|
|
4
4
|
### Added
|
|
5
5
|
- ...
|
|
6
6
|
### Changed/Removed
|
|
@@ -9,6 +9,77 @@
|
|
|
9
9
|
- ...
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
+
## v0.12.0 - BREAKING CHANGES
|
|
13
|
+
A big release with several breaking changes, not all of which can be listed below. The headline features for this release are the introduction of a database adapter, allowing Wgit to work with practically any underlying database system; and a custom in-house text extractor.
|
|
14
|
+
### Added
|
|
15
|
+
- `Wgit::Database::DatabaseAdapter` class to allow the easy development of other database adapters that work with Wgit.
|
|
16
|
+
- `Wgit::Database::InMemory` database adapter class and logic for quick and easy usage of Wgit on the fly (without needing a MongoDB instance to be running). This also serves as an example of how to write your own database adapter class.
|
|
17
|
+
- `Wgit::HTMLToText` class and logic for extracting text from a HTML string. This is now how a `Wgit::Document` extracts its text for searching etc. This class is different in that it not only focuses on the elements we specify, but also applies those elements display in how it delimits where one sentence ends and the next starts e.g. `<span>` is `:inline` etc.
|
|
18
|
+
- `Wgit::Document#nearest_fragment` method which allows you to search for the nearest fragement (#blah) to a piece of text and/or element type.
|
|
19
|
+
- `Wgit::Model.search_fields` and `.set_search_fields` for setting which search fields are used in document and database adapter searches.
|
|
20
|
+
- `Wgit::Model.include_doc_html` and `include_doc_score` methods to set in one place if html/score is included in the corresponding document model output.
|
|
21
|
+
- `Wgit::Assertable#common_arr_types` method.
|
|
22
|
+
- `Wgit::Utils.pprint(display:)` param to turn off all logs easily (by setting from ENV etc).
|
|
23
|
+
- `Wgit::Crawler#crawl_site(max_pages:)` param to quit the crawl early.
|
|
24
|
+
- `Wgit::Utils.pprint_search_results(include_score:)` param to print the score of each result.
|
|
25
|
+
- `Wgit::Utils.pprint_all_search_results` method to print all matches for each result.
|
|
26
|
+
- `Wgit::DSL#search` params `include_score:` and `top_result_only:`.
|
|
27
|
+
### Changed/Removed
|
|
28
|
+
- Update Wgit to work with ruby v3 and above, removed support for older versions.
|
|
29
|
+
- Removed default extractors `meta_robots` and `meta_wgit` without losing any functionality.
|
|
30
|
+
- `Wgit::Database::Model` is now moved up a level to become `Wgit::Model`.
|
|
31
|
+
- `Wgit::Database` is now `Wgit::Database::MongoDB` and is alised to `Wgit::Database.adapter_class`.
|
|
32
|
+
- Renamed any `Wgit::Database` and `Wgit::DSL` methods called `#clear_*` to be `#empty_*`.
|
|
33
|
+
- Moved `Wgit::MongoDB#search!` to `Wgit::DSL#search`.
|
|
34
|
+
- Renamed `Wgit::MongoDB#search_text` to `Wgit::Database::MongoDB#search!`.
|
|
35
|
+
- Reworked `Wgit::DSL` methods to accept a database param instead of a connection_string. This offers better flexibility.
|
|
36
|
+
- Updated the Wgit `Dockerfile` to pull from `mongo:latest`.
|
|
37
|
+
- `Wgit::Document#search` now searches more than just it's text. See `Wgit::Model.search_fields` for more information.
|
|
38
|
+
- `Wgit::Document` now has the following search methods: `#search`, `#search_text`, `#search_text!`. See their documentation and source code for more information.
|
|
39
|
+
- `Wgit::Document.define_extractor` now accepts a `nil` xpath parameter which omits the xpath search.
|
|
40
|
+
- `Wgit::Indexer#index_*` methods now use `:skip` block return value to avoid DB upserts.
|
|
41
|
+
- Updated `Wgit::Crawler.new` to accept `ferrum_opts:` which are passed to directly ferrum on init.
|
|
42
|
+
- `Wgit::Document#search` now accepts a `&block` which yields the results Hash.
|
|
43
|
+
- Updated `Wgit::Indexer#index_*` methods to accept `ENV["WGIT_IGNORE_ROBOTS_TXT"]` ignoring a site's robot.txt file.
|
|
44
|
+
### Fixed
|
|
45
|
+
- Issue [Document#search only searches the text](https://github.com/michaeltelford/wgit/issues/2)
|
|
46
|
+
- Issue [Document#search doesn't find certain text](https://github.com/michaeltelford/wgit/issues/20)
|
|
47
|
+
- Issue with `Wgit::Document#search(whole_sentence:)` search capability by updating the regex used.
|
|
48
|
+
- Issue with `Wgit::Document#search` which now totals the text score for duplicated results.
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## v0.11.0 - BREAKING CHANGES
|
|
52
|
+
This release is a biggie with the main headline being the introduction of robots.txt support (see below). This release introduces several breaking changes so take care when updating your current version of Wgit.
|
|
53
|
+
### Added
|
|
54
|
+
- Ability to prevent indexing via `robots.txt` and `noindex` values in HTML `meta` elements and HTTP response header `X-Robots-Tag`. See new class `Wgit::RobotsParser` and the updated `Wgit::Indexer#index_*` methods. Also see the [wiki article](https://github.com/michaeltelford/wgit/wiki/How-To-Prevent-Indexing) on the subject.
|
|
55
|
+
- `Wgit::RobotsParser` class for parsing `robots.txt` files.
|
|
56
|
+
- `Wgit::Response#no_index?` and `Wgit::Document#no_index?` methods (see wiki article above).
|
|
57
|
+
- Added two new default extractors which extract robots meta elements for use in `Wgit::Document#no_index?`.
|
|
58
|
+
- Added `Wgit::Document.to_h_ignore_vars` Array for user manipulation.
|
|
59
|
+
- Added `Wgit::Utils.pprint` method to aid debugging.
|
|
60
|
+
- Added `Wgit::Utils.sanitize_url` method.
|
|
61
|
+
- Added `Wgit::Indexer#index_www(max_urls_per_iteration:, ...)` param.
|
|
62
|
+
- Added `Wgit::Url#redirects` and `#redirects=` methods.
|
|
63
|
+
- Added `Wgit::Url#redirects_journey` used by `Wgit::Indexer` to insert a Url and it's redirects.
|
|
64
|
+
- Added `Wgit::Database#bulk_upsert` which `Wgit::Indexer` now uses where possible. This reduces the total database calls made during an index operation.
|
|
65
|
+
### Changed/Removed
|
|
66
|
+
- Updated `Wgit::Indexer#index_*` methods to honour index prevention methods (see the [wiki article](https://github.com/michaeltelford/wgit/wiki/How-To-Prevent-Indexing)).
|
|
67
|
+
- Updated `Wgit::Utils.sanitize*` methods so they no longer modify the receiver.
|
|
68
|
+
- Updated `Wgit::Crawler#crawl_url` to always return the crawled `Wgit::Document`. If relying on `nil` in your code, you should now use `doc.empty?` instead.
|
|
69
|
+
- Updated `Wgit::Indexer` method logs.
|
|
70
|
+
- Updated/added custom class `#inspect` methods.
|
|
71
|
+
- Renamed `Wgit::Utils.printf_search_results` to `pprint_search_results`.
|
|
72
|
+
- Renamed `Wgit::Url#concat` to `#join`. The `#concat` method is now `String#concat`.
|
|
73
|
+
- Updated `Wgit::Indexer` methods to now write external Urls to the Database as: `doc.external_urls.map(&:to_origin)` meaning `http://example.com/about` becomes `http://example.com`.
|
|
74
|
+
- Updated the following methods to no longer omit trailing slashes from Urls: `Wgit::Url` - `#to_path`, `#omit_base`, `#omit_origin` and `Wgit::Document` - `#internal_links`, `#internal_absolute_links`, `#external_links`. For an average website, this results in ~30% less network requests when crawling.
|
|
75
|
+
- Updated Ruby version to `3.3.0`.
|
|
76
|
+
- Updated all bundle dependencies to latest versions, see `Gemfile.lock` for exact versions.
|
|
77
|
+
### Fixed
|
|
78
|
+
- `Wgit::Crawler#crawl_site` now internally records all redirects for a given Url.
|
|
79
|
+
- `Wgit::Crawler#crawl_site` infinite loop when using Wgit on a Ruby version > `3.0.2`.
|
|
80
|
+
- Various other minor fixes/improvements throughout the code base.
|
|
81
|
+
---
|
|
82
|
+
|
|
12
83
|
## v0.10.8
|
|
13
84
|
### Added
|
|
14
85
|
- Custom `#inspect` methods to `Wgit::Url` and `Wgit::Document` classes.
|
data/CODE_OF_CONDUCT.md
CHANGED
|
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
|
|
|
55
55
|
## Enforcement
|
|
56
56
|
|
|
57
57
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
58
|
-
reported by contacting the project team
|
|
58
|
+
reported by contacting the project team on Github. All
|
|
59
59
|
complaints will be reviewed and investigated and will result in a response that
|
|
60
60
|
is deemed necessary and appropriate to the circumstances. The project team is
|
|
61
61
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
data/CONTRIBUTING.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Consult
|
|
4
4
|
|
|
5
|
-
Before you make a contribution, reach out
|
|
5
|
+
Before you make a contribution, reach out on Github about what changes need made. Otherwise, your time spent might be wasted. Once you're clear on what needs done follow the technical steps below.
|
|
6
6
|
|
|
7
7
|
## Technical Steps
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ Before you make a contribution, reach out to michael.telford@live.com about what
|
|
|
12
12
|
- Write some code
|
|
13
13
|
- Re-run the tests (which now hopefully pass)
|
|
14
14
|
- Push your branch to your `origin` remote
|
|
15
|
-
- Open a GitHub Pull Request (with the target branch
|
|
15
|
+
- Open a GitHub Pull Request (with the target branch as wgit's (upstream) `master`)
|
|
16
16
|
- Apply any requested changes
|
|
17
17
|
- Wait for your PR to be merged
|
|
18
18
|
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://rubygems.org/gems/wgit)
|
|
4
4
|
[](https://rubygems.org/gems/wgit)
|
|
5
|
-
[](https://github.com/michaeltelford/wgit/actions)
|
|
6
6
|
[](http://inch-ci.org/github/michaeltelford/wgit)
|
|
7
7
|
[](https://www.codacy.com/app/michaeltelford/wgit?utm_source=github.com&utm_medium=referral&utm_content=michaeltelford/wgit&utm_campaign=Badge_Grade)
|
|
8
8
|
|
|
@@ -13,12 +13,12 @@ Wgit is a HTML web crawler, written in Ruby, that allows you to programmatically
|
|
|
13
13
|
Wgit was primarily designed to crawl static HTML websites to index and search their content - providing the basis of any search engine; but Wgit is suitable for many application domains including:
|
|
14
14
|
|
|
15
15
|
- URL parsing
|
|
16
|
-
- Document content extraction (data mining)
|
|
17
|
-
-
|
|
16
|
+
- Document content extraction (data mining etc)
|
|
17
|
+
- Recursive website crawling (indexing, statistical analysis etc)
|
|
18
18
|
|
|
19
19
|
Wgit provides a high level, easy-to-use API and DSL that you can use in your own applications and scripts.
|
|
20
20
|
|
|
21
|
-
Check out this [demo search engine](https://wgit-search-engine.fly.dev) - [built](https://github.com/michaeltelford/search_engine) using Wgit and
|
|
21
|
+
Check out this [demo search engine](https://wgit-search-engine.fly.dev) - [built](https://github.com/michaeltelford/search_engine) using Wgit, Sinatra and MongoDB - deployed to [fly.io](https://fly.io). Try searching for something that's Ruby related like "Matz" or "Rails".
|
|
22
22
|
|
|
23
23
|
## Table Of Contents
|
|
24
24
|
|
|
@@ -78,7 +78,7 @@ Which outputs:
|
|
|
78
78
|
]
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
Great! But what if we want to crawl and store the content in a database, so that it can be searched? Wgit makes it easy to index and search HTML using [MongoDB](https://www.mongodb.com/):
|
|
81
|
+
Great! But what if we want to crawl and store the content in a database, so that it can be searched? Wgit makes it easy to index and search HTML using [MongoDB](https://www.mongodb.com/) (by default):
|
|
82
82
|
|
|
83
83
|
```ruby
|
|
84
84
|
require 'wgit'
|
|
@@ -87,7 +87,7 @@ include Wgit::DSL
|
|
|
87
87
|
|
|
88
88
|
Wgit.logger.level = Logger::WARN
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
ENV['WGIT_CONNECTION_STRING'] = 'mongodb://user:password@localhost/crawler'
|
|
91
91
|
|
|
92
92
|
start 'http://quotes.toscrape.com/tag/humor/'
|
|
93
93
|
follow "//li[@class='next']/a/@href"
|
|
@@ -109,11 +109,11 @@ http://quotes.toscrape.com/tag/humor/page/2/
|
|
|
109
109
|
...
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
Using a
|
|
112
|
+
Using a database client, we can see that the two web pages have been indexed, along with their extracted *quotes* and *authors*:
|
|
113
113
|
|
|
114
114
|

|
|
115
115
|
|
|
116
|
-
The [DSL](https://github.com/michaeltelford/wgit/wiki/How-To-Use-The-DSL) makes it easy to write scripts for experimenting with. Wgit's DSL is simply a wrapper around the underlying classes
|
|
116
|
+
The [DSL](https://github.com/michaeltelford/wgit/wiki/How-To-Use-The-DSL) makes it easy to write scripts for experimenting with. Wgit's DSL is simply a wrapper around the underlying classes. For comparison, here is the quote example re-written using the Wgit API *instead of* the DSL:
|
|
117
117
|
|
|
118
118
|
```ruby
|
|
119
119
|
require 'wgit'
|
|
@@ -143,9 +143,9 @@ puts JSON.generate(quotes)
|
|
|
143
143
|
There are many [other HTML crawlers](https://awesome-ruby.com/#-web-crawling) out there so why use Wgit?
|
|
144
144
|
|
|
145
145
|
- Wgit has excellent unit testing, 100% documentation coverage and follows [semantic versioning](https://semver.org/) rules.
|
|
146
|
-
- Wgit excels at crawling an entire website's HTML out of the box. Many alternative crawlers require you to provide the `xpath` needed to *follow* the next URLs to crawl. Wgit by default, crawls the entire site by extracting its internal links pointing to the same host.
|
|
146
|
+
- Wgit excels at crawling an entire website's HTML out of the box. Many alternative crawlers require you to provide the `xpath` needed to *follow* the next URLs to crawl. Wgit by default, crawls the entire site by extracting its internal links pointing to the same host - no `xpath` needed.
|
|
147
147
|
- Wgit allows you to define content *extractors* that will fire on every subsequent crawl; be it a single URL or an entire website. This enables you to focus on the content you want.
|
|
148
|
-
- Wgit can index (crawl and
|
|
148
|
+
- Wgit can index (crawl and save) HTML to a database making it a breeze to build custom search engines. You can also specify which page content gets searched, making the search more meaningful. For example, here's a script that will index the Wgit [wiki](https://github.com/michaeltelford/wgit/wiki) articles:
|
|
149
149
|
|
|
150
150
|
```ruby
|
|
151
151
|
require 'wgit'
|
|
@@ -164,6 +164,9 @@ indexer = Wgit::Indexer.new
|
|
|
164
164
|
indexer.index_site(wiki, **opts)
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
+
- Wgit supports different databases through the use of "adapter" classes, which you can write to support your own database of choice.
|
|
168
|
+
- Wgit's built in indexing methods will by default, honour a site's `robots.txt` rules. There's also a handy `robots.txt` parser that you can use in your own code.
|
|
169
|
+
|
|
167
170
|
## Why Not Wgit?
|
|
168
171
|
|
|
169
172
|
So why might you not use Wgit, I hear you ask?
|
|
@@ -176,9 +179,9 @@ So why might you not use Wgit, I hear you ask?
|
|
|
176
179
|
|
|
177
180
|
Only MRI Ruby is tested and supported, but Wgit may work with other Ruby implementations.
|
|
178
181
|
|
|
179
|
-
Currently, the
|
|
182
|
+
Currently, the supported range of MRI Ruby versions is:
|
|
180
183
|
|
|
181
|
-
`ruby '
|
|
184
|
+
`ruby '~> 3.0'` a.k.a. between Ruby 3.0 and up to but not including Ruby 4.0. Wgit will probably work fine with older versions but best to upgrade if possible.
|
|
182
185
|
|
|
183
186
|
### Using Bundler
|
|
184
187
|
|
|
@@ -208,10 +211,11 @@ Installing the Wgit gem adds a `wgit` executable to your `$PATH`. The executable
|
|
|
208
211
|
The `wgit` executable does the following things (in order):
|
|
209
212
|
|
|
210
213
|
1. `require wgit`
|
|
211
|
-
2.
|
|
212
|
-
3.
|
|
214
|
+
2. Loads an `.env` file (if one exists in either the local or home directory, which ever is found first)
|
|
215
|
+
3. `eval`'s a `.wgit.rb` file (if one exists in either the local or home directory, which ever is found first)
|
|
216
|
+
4. Starts an interactive shell (using `pry` if it's installed, or `irb` if not)
|
|
213
217
|
|
|
214
|
-
The `.wgit.rb` file can be used to seed fixture data or define helper functions for the session. For example, you could define a function which indexes your website for quick and easy searching everytime you start
|
|
218
|
+
The `.wgit.rb` file can be used to seed fixture data or define helper functions for the session. For example, you could define a function which indexes your website for quick and easy searching everytime you start `wgit`.
|
|
215
219
|
|
|
216
220
|
## License
|
|
217
221
|
|
|
@@ -237,14 +241,14 @@ And you're good to go!
|
|
|
237
241
|
|
|
238
242
|
### Tooling
|
|
239
243
|
|
|
240
|
-
Wgit uses the [
|
|
244
|
+
Wgit uses the [toys](https://github.com/dazuma/toys) gem (instead of Rake) for task invocation. Always run `toys` as `bundle exec toys`. For a full list of available tasks a.k.a. tools, run `bundle exec toys --tools`. You can search for a tool using `bundle exec toys -s tool_name`. The most commonly used tools are listed below...
|
|
241
245
|
|
|
242
|
-
Run `toys db` to see a list of database related tools, enabling you to run a Mongo DB instance locally using Docker. Run `toys test` to execute the tests.
|
|
246
|
+
Run `bundle exec toys db` to see a list of database related tools, enabling you to run a Mongo DB instance locally using Docker. Run `bundle exec toys test` to execute the tests.
|
|
243
247
|
|
|
244
|
-
To generate code documentation locally, run `toys yardoc`. To browse the docs in a browser run `toys yardoc --serve`. You can also use the `yri` command line tool e.g. `yri Wgit::Crawler#crawl_site` etc.
|
|
248
|
+
To generate code documentation locally, run `bundle exec toys yardoc`. To browse the docs in a browser run `bundle exec toys yardoc --serve`. You can also use the `yri` command line tool e.g. `yri Wgit::Crawler#crawl_site` etc.
|
|
245
249
|
|
|
246
|
-
To install this gem onto your local machine, run `toys install` and follow the prompt.
|
|
250
|
+
To install this gem onto your local machine, run `bundle exec toys install` and follow the prompt.
|
|
247
251
|
|
|
248
252
|
### Console
|
|
249
253
|
|
|
250
|
-
You can run `toys console` for an interactive shell using the `./bin/wgit` executable. The `toys setup` task will have created an `.env` and `.wgit.rb` file which get loaded by the executable. You can use the contents of this [gist](https://gist.github.com/michaeltelford/b90d5e062da383be503ca2c3a16e9164) to turn the executable into a development console. It defines some useful functions, fixtures and connects to the database etc. Don't forget to set the `WGIT_CONNECTION_STRING` in the `.env` file.
|
|
254
|
+
You can run `bundle exec toys console` for an interactive shell using the `./bin/wgit` executable. The `bundle exec toys setup` task will have created an `.env` and `.wgit.rb` file which get loaded by the executable. You can use the contents of this [gist](https://gist.github.com/michaeltelford/b90d5e062da383be503ca2c3a16e9164) to turn the executable into a development console. It defines some useful functions, fixtures and connects to the database etc. Don't forget to set the `WGIT_CONNECTION_STRING` in the `.env` file.
|
data/bin/wgit
CHANGED
|
@@ -1,39 +1,95 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "wgit"
|
|
4
|
+
|
|
5
|
+
# Shorten the filepath for nicer output to the user.
|
|
6
|
+
def format_path(dir, path)
|
|
7
|
+
return path.gsub(dir, ".") if dir == Dir.pwd
|
|
8
|
+
return path.gsub(dir, "~") if dir == Dir.home
|
|
9
|
+
|
|
10
|
+
path
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Load .env file (if it exists somewhere).
|
|
14
|
+
def load_env
|
|
15
|
+
begin
|
|
16
|
+
require "dotenv"
|
|
17
|
+
rescue LoadError
|
|
18
|
+
puts "Skipping .env load because 'dotenv' isn't installed"
|
|
19
|
+
puts
|
|
20
|
+
return false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
puts "Searching for .env file in local and home directories..."
|
|
24
|
+
success = false
|
|
25
|
+
|
|
26
|
+
[Dir.pwd, Dir.home].each do |dir|
|
|
27
|
+
path = "#{dir}/.env"
|
|
28
|
+
next unless File.exist?(path)
|
|
29
|
+
|
|
30
|
+
puts "Loading #{format_path(dir, path)}"
|
|
31
|
+
puts "Call `load_env` after changes to re-load the environment variables"
|
|
32
|
+
|
|
33
|
+
Dotenv.load(path)
|
|
34
|
+
success = true
|
|
35
|
+
|
|
36
|
+
break
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
puts
|
|
40
|
+
|
|
41
|
+
success
|
|
42
|
+
end
|
|
4
43
|
|
|
5
44
|
# Eval .wgit.rb file (if it exists somewhere).
|
|
6
|
-
def eval_wgit
|
|
7
|
-
puts
|
|
45
|
+
def eval_wgit
|
|
46
|
+
puts "Searching for .wgit.rb file in local and home directories..."
|
|
47
|
+
success = false
|
|
8
48
|
|
|
9
|
-
[
|
|
49
|
+
[Dir.pwd, Dir.home].each do |dir|
|
|
10
50
|
path = "#{dir}/.wgit.rb"
|
|
11
51
|
next unless File.exist?(path)
|
|
12
52
|
|
|
13
|
-
puts "Eval'ing #{path}"
|
|
14
|
-
puts
|
|
53
|
+
puts "Eval'ing #{format_path(dir, path)}"
|
|
54
|
+
puts "Call `eval_wgit` after changes to re-eval the file"
|
|
55
|
+
|
|
15
56
|
eval(File.read(path))
|
|
57
|
+
success = true
|
|
16
58
|
|
|
17
59
|
break
|
|
18
60
|
end
|
|
19
61
|
|
|
20
|
-
|
|
21
|
-
end
|
|
62
|
+
puts
|
|
22
63
|
|
|
23
|
-
|
|
24
|
-
|
|
64
|
+
success
|
|
65
|
+
end
|
|
25
66
|
|
|
67
|
+
# Choose and return which REPL class to use.
|
|
26
68
|
# Use Pry if installed or fall back to IRB.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
69
|
+
def repl_class
|
|
70
|
+
begin
|
|
71
|
+
require "pry"
|
|
72
|
+
klass = Pry
|
|
73
|
+
rescue LoadError
|
|
74
|
+
require "irb"
|
|
75
|
+
klass = IRB
|
|
76
|
+
|
|
77
|
+
puts "Using 'irb' REPL because 'pry' isn't installed"
|
|
78
|
+
puts
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
klass
|
|
35
82
|
end
|
|
36
83
|
|
|
84
|
+
### START OF EXECUTABLE ###
|
|
85
|
+
|
|
86
|
+
load_env
|
|
87
|
+
eval_wgit
|
|
88
|
+
klass = repl_class
|
|
89
|
+
|
|
90
|
+
puts Wgit.version_str
|
|
91
|
+
puts "#{'-' * Wgit.version_str.size}\n\n"
|
|
92
|
+
|
|
37
93
|
klass.start
|
|
38
94
|
|
|
39
|
-
puts
|
|
95
|
+
puts "Interactive wgit session complete"
|
data/lib/wgit/assertable.rb
CHANGED
|
@@ -4,11 +4,18 @@ module Wgit
|
|
|
4
4
|
# Module containing assertion methods including type checking and duck typing.
|
|
5
5
|
module Assertable
|
|
6
6
|
# Default type fail message.
|
|
7
|
-
DEFAULT_TYPE_FAIL_MSG =
|
|
7
|
+
DEFAULT_TYPE_FAIL_MSG = "Expected: %s, Actual: %s"
|
|
8
|
+
|
|
8
9
|
# Wrong method message.
|
|
9
|
-
NON_ENUMERABLE_MSG =
|
|
10
|
+
NON_ENUMERABLE_MSG = "Expected an Enumerable responding to #each, not: %s"
|
|
11
|
+
|
|
12
|
+
# Enumerable with more than one type across it's elements.
|
|
13
|
+
MIXED_ENUMERABLE_MSG = "Expected an Enumerable with elements of a single \
|
|
14
|
+
common type"
|
|
15
|
+
|
|
10
16
|
# Default duck fail message.
|
|
11
17
|
DEFAULT_DUCK_FAIL_MSG = "%s doesn't respond_to? %s"
|
|
18
|
+
|
|
12
19
|
# Default required keys message.
|
|
13
20
|
DEFAULT_REQUIRED_KEYS_MSG = "Some or all of the required keys are not \
|
|
14
21
|
present: %s"
|
|
@@ -47,6 +54,25 @@ present: %s"
|
|
|
47
54
|
arr.each { |obj| assert_types(obj, type_or_types, msg) }
|
|
48
55
|
end
|
|
49
56
|
|
|
57
|
+
# All objects within arr must match one of the types listed in
|
|
58
|
+
# type_or_types; or an exception is raised using msg, if provided.
|
|
59
|
+
# Ancestors of the same type are allowed and considered common.
|
|
60
|
+
#
|
|
61
|
+
# @param arr [Enumerable#each] Enumerable of objects to type check.
|
|
62
|
+
# @param type_or_types [Type, Array<Type>] The allowed type(s).
|
|
63
|
+
# @param msg [String] The raised StandardError message, if provided.
|
|
64
|
+
# @raise [StandardError] If the assertion fails.
|
|
65
|
+
# @return [Object] The given arr on successful assertion.
|
|
66
|
+
def assert_common_arr_types(arr, type_or_types, msg = nil)
|
|
67
|
+
raise format(NON_ENUMERABLE_MSG, arr.class) unless arr.respond_to?(:each)
|
|
68
|
+
|
|
69
|
+
type = arr.first.class
|
|
70
|
+
type_match = arr.all? { |obj| type.ancestors.include?(obj.class) }
|
|
71
|
+
raise MIXED_ENUMERABLE_MSG unless type_match
|
|
72
|
+
|
|
73
|
+
assert_arr_types(arr, type_or_types, msg)
|
|
74
|
+
end
|
|
75
|
+
|
|
50
76
|
# The obj_or_objs must respond_to? all of the given methods or an
|
|
51
77
|
# Exception is raised using msg, if provided.
|
|
52
78
|
#
|
|
@@ -75,7 +101,7 @@ present: %s"
|
|
|
75
101
|
# @raise [KeyError] If the assertion fails.
|
|
76
102
|
# @return [Hash] The given hash on successful assertion.
|
|
77
103
|
def assert_required_keys(hash, keys, msg = nil)
|
|
78
|
-
msg ||= format(DEFAULT_REQUIRED_KEYS_MSG, keys.join(
|
|
104
|
+
msg ||= format(DEFAULT_REQUIRED_KEYS_MSG, keys.join(", "))
|
|
79
105
|
all_present = keys.all? { |key| hash.keys.include? key }
|
|
80
106
|
raise KeyError, msg unless all_present
|
|
81
107
|
|
|
@@ -86,7 +112,7 @@ present: %s"
|
|
|
86
112
|
|
|
87
113
|
# obj must respond_to? all methods or an exception is raised.
|
|
88
114
|
def _assert_respond_to(obj, methods, msg = nil)
|
|
89
|
-
raise
|
|
115
|
+
raise "methods must respond_to? :all?" unless methods.respond_to?(:all?)
|
|
90
116
|
|
|
91
117
|
msg ||= format(DEFAULT_DUCK_FAIL_MSG, "#{obj.class} (#{obj})", methods)
|
|
92
118
|
match = methods.all? { |method| obj.respond_to?(method) }
|
|
@@ -95,7 +121,8 @@ present: %s"
|
|
|
95
121
|
obj
|
|
96
122
|
end
|
|
97
123
|
|
|
98
|
-
|
|
99
|
-
|
|
124
|
+
alias_method :assert_type, :assert_types
|
|
125
|
+
alias_method :assert_arr_type, :assert_arr_types
|
|
126
|
+
alias_method :assert_common_arr_type, :assert_common_arr_types
|
|
100
127
|
end
|
|
101
128
|
end
|
data/lib/wgit/core_ext.rb
CHANGED