-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial DynamicDeps support. #201
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
d322e14
Initial DynamicDeps support.
wRAR fff751c
More DynamicDeps tests.
wRAR a9dba26
Add docs for DynamicDeps.
wRAR 6f7e5d1
Extract and test _get_dynamic_deps_factory().
wRAR 9d6dde9
Cleanup.
wRAR efdbed1
Refactor _get_dynamic_deps_factory.
wRAR f6461cc
More tests for dynamic deps.
wRAR 1b9c00a
Small fixes.
wRAR 887e2fe
Improve test_dynamic_deps_mix().
wRAR 9016a7b
Improve DynamicDeps docs.
wRAR File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
.. _dynamic-deps: | ||
|
||
==================== | ||
Dynamic dependencies | ||
==================== | ||
|
||
Normally the dependencies for a callback are specified statically, as type | ||
hints for its arguments: | ||
|
||
.. code-block:: python | ||
|
||
import scrapy | ||
|
||
|
||
class BooksSpider(scrapy.Spider): | ||
... | ||
|
||
def start_requests(self): | ||
yield scrapy.Request("http://books.toscrape.com/", self.parse_book) | ||
|
||
|
||
def parse_book(self, response, book_page: BookPage, other_dep: OtherDep): | ||
... | ||
|
||
In some cases some or all of the dependencies need to be specified dynamically | ||
instead, e.g. because they need to be different for different requests using | ||
the same callback. You can use :class:`scrapy_poet.DynamicDeps | ||
<scrapy_poet.injection.DynamicDeps>` for this. If you add a callback argument | ||
with this type you can pass a list of additional dependency types in the | ||
request meta dictionary using the "inject" key: | ||
|
||
.. code-block:: python | ||
|
||
import scrapy | ||
|
||
|
||
class BooksSpider(scrapy.Spider): | ||
... | ||
|
||
def start_requests(self): | ||
yield scrapy.Request( | ||
"http://books.toscrape.com/", | ||
self.parse_book, | ||
meta={"inject": [OtherDep]}, | ||
) | ||
|
||
|
||
def parse_book(self, response, book_page: BookPage, dynamic: DynamicDeps): | ||
# access the dynamic dependency values by their type: | ||
other_dep = dynamic[OtherDep] | ||
... | ||
# or get them and their types at the run time: | ||
for dep_type, dep in dynamic.items(): | ||
if dep_type is OtherDep: | ||
... | ||
|
||
The types passed this way are used in the dependency resolution as usual, with | ||
the created instances available in the :class:`scrapy_poet.DynamicDeps | ||
<scrapy_poet.injection.DynamicDeps>` instance, which is a dictionary with | ||
dependency types as keys and their instances as values. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
from .api import DummyResponse, callback_for | ||
from .downloadermiddlewares import DownloaderStatsMiddleware, InjectionMiddleware | ||
from .injection import DynamicDeps | ||
from .page_input_providers import HttpResponseProvider, PageObjectInputProvider | ||
from .spidermiddlewares import RetryMiddleware | ||
from ._request_fingerprinter import ScrapyPoetRequestFingerprinter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to get a list of the created dependencies in the DynamicDeps (i.e. the available keys)? It seems we should document it. Currently only getting by type is documented, if I'm not mistaken.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assumed the user already knows which deps are there because it's they who set the meta key, but in other uses cases (which?) they can look at
dynamic.keys()
, do you want to document this or are you thinking about something else?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There could be a single callback which gets requests from different places, with different "inject" meta; this "inject" meta can be dynamic as well. For example, it can be a list of item classes to extract from a particular page, configured at spider start. Isn't it a point of DynamicDeps that the callback doesn't know what are the dependencies? Otherwise they can be specified in a signature.
As for the documentation, I think documenting DynamicDeps as a dict subclass could be enough.