From 9523ca635f1c13aa282969ef25cff8764fcd0380 Mon Sep 17 00:00:00 2001 From: Markus Vogl Date: Tue, 1 Oct 2019 22:43:28 +0200 Subject: [PATCH 1/3] Repair it to search for multiple sources and change suggested pages to look like they are working --- README.rst | 31 ++++++++++++++++--------------- main.py | 17 +++++++---------- stackoverflow/__init__.py | 30 +++++++++++++++++++----------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/README.rst b/README.rst index 16a7e43..7b5a7d8 100644 --- a/README.rst +++ b/README.rst @@ -6,9 +6,9 @@ Overflow? Let’s take it one step further. -| ``from stackoverflow import quick_sort`` will go through the search +| ``from stackoverflow import sort`` will go through the search results -| of ``[python] quick sort`` looking for the largest code block that +| of ``[python] sort`` looking for the largest code block that doesn’t | syntax error in the highest voted answer from the highest voted question @@ -18,20 +18,21 @@ Let’s take it one step further. .. code:: python - >>> from stackoverflow import quick_sort, split_into_chunks - - >>> print(quick_sort.sort([1, 3, 2, 5, 4])) - [1, 2, 3, 4, 5] - - >>> print(list(split_into_chunks.chunk("very good chunk func"))) - ['very ', 'good ', 'chunk', ' func'] - - >>> print("I wonder who made split_into_chunks", split_into_chunks.__author__) - I wonder who made split_into_chunks https://stackoverflow.com/a/35107113 - - >>> print("but what's the license? Can I really use this?", quick_sort.__license__) + from stackoverflow import sort + print(sort.sort_iterable([3,1,2])) + >>> + print("I wonder who made sort", sort.__author__) + print("but what's the license? Can I really use this?", sort.__license__) + + from stackoverflow import file_copy + print(file_copy.copyfile("main.py", "main2.py")) + + """ prints + [1, 2, 3] + I wonder who made sort https://stackoverflow.com/a/49073645 but what's the license? Can I really use this? CC BY-SA 3.0 - >>> assert("nice, attribution!") + ████████████████████ [100.00%]main2.py + """ This module is licensed under whatever license you want it to be as long as the license is compatible with the fact that I blatantly diff --git a/main.py b/main.py index 826071a..6220340 100644 --- a/main.py +++ b/main.py @@ -1,10 +1,7 @@ -from stackoverflow import quick_sort, split_into_chunks -print(quick_sort.sort([1, 3, 2, 5, 4])) -print(list(split_into_chunks.chunk("very good chunk func"))) -print("gotta take a break") -from time import time -t1 = time() -from stackoverflow import time_delay -print("that's enough, let's continue", time()-t1) -print("I wonder who made split_into_chunks", split_into_chunks.__author__) -print("but what's the license? Can I really use this?", quick_sort.__license__) +from stackoverflow import sort +print(sort.sort_iterable([3,1,2])) +print("I wonder who made sort", sort.__author__) +print("but what's the license? Can I really use this?", sort.__license__) + +from stackoverflow import file_copy +print(file_copy.copyfile("main.py", "main2.py")) \ No newline at end of file diff --git a/stackoverflow/__init__.py b/stackoverflow/__init__.py index 73500cb..f7e3cab 100644 --- a/stackoverflow/__init__.py +++ b/stackoverflow/__init__.py @@ -2,11 +2,11 @@ import html import re import sys +from copy import copy from importlib._bootstrap import spec_from_loader import requests - class StackOverflowImporter: """ `from stackoverflow import quick_sort` will go through the search results @@ -19,9 +19,8 @@ class StackOverflowImporter: @classmethod def find_spec(cls, fullname, path=None, target=None): spec = spec_from_loader(fullname, cls, origin='hell') - spec.__license__ = "CC BY-SA 3.0" - spec._url = cls._fetch_url(spec.name) - spec._code, spec.__author__ = cls._fetch_code(spec._url) + spec.__license__ = "CC BY-SA 3.0" # todo: fix this + spec._code, spec._url, spec.__author__ = cls.get_code_url_author(spec.name) return spec @classmethod @@ -36,16 +35,24 @@ def exec_module(cls, module=None): exec(module._code, module.__dict__) except: print(module._url) - print(module._code) + print(module) raise @classmethod - def get_code(cls, fullname): - return compile(cls._fetch_code(cls._fetch_url(fullname)), 'StackOverflow.com/' + fullname, 'exec') + def get_code_url_author(cls, fullname): + urls = cls._fetch_urls(fullname) + for url in urls: + try: + code, author = cls._fetch_code(url) + return compile(code, 'StackOverflow.com/' + fullname, 'exec') , url, author + except ImportError: + pass + raise ImportError("This question ain't got no good code.") + @classmethod def get_source(cls, fullname): - return cls.get_code(fullname) + return cls.get_code_url_author(fullname)[0] @classmethod def is_package(cls, fullname): @@ -54,7 +61,7 @@ def is_package(cls, fullname): ############################ @classmethod - def _fetch_url(cls, query): + def _fetch_urls(cls, query): query = query.lower().replace("stackoverflow.", "").replace("_", " ") ans = requests.get(cls.API_URL + "/search", { "order": "desc", @@ -65,7 +72,8 @@ def _fetch_url(cls, query): }).json() if not ans["items"]: raise ImportError("Couldn't find any question matching `" + query + "`") - return ans["items"][0]["link"] + items = ans["items"] + return [i["link"] for i in items] @classmethod def _fetch_code(cls, url): @@ -74,7 +82,7 @@ def _fetch_code(cls, url): @staticmethod def _find_code_in_html(s): - answers = re.findall(r'
Date: Tue, 1 Oct 2019 22:52:59 +0200 Subject: [PATCH 2/3] Modules are now callable, see issue #14 --- README.rst | 2 +- stackoverflow/__init__.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 7b5a7d8..c4393ce 100644 --- a/README.rst +++ b/README.rst @@ -16,7 +16,7 @@ Let’s take it one step further. python | code, it checks the next highest voted answer for code blocks. -.. code:: python +.. code:: pytho from stackoverflow import sort print(sort.sort_iterable([3,1,2])) diff --git a/stackoverflow/__init__.py b/stackoverflow/__init__.py index f7e3cab..b0f96ba 100644 --- a/stackoverflow/__init__.py +++ b/stackoverflow/__init__.py @@ -21,7 +21,23 @@ def find_spec(cls, fullname, path=None, target=None): spec = spec_from_loader(fullname, cls, origin='hell') spec.__license__ = "CC BY-SA 3.0" # todo: fix this spec._code, spec._url, spec.__author__ = cls.get_code_url_author(spec.name) + cls.make_callable(spec) return spec + + @classmethod + def make_callable(cls, spec): + """ to be callable, your (copy of) __class__ must have a __call__ """ + methods = spec._code.co_names + if methods: + spec.__class__ = copy(spec.__class__) + spec.__class__.method = methods[0] + def call(cls, *arg, **varg): + """ during find_spec, the method itself is not in cls -> dynamic calling """ + method = cls.__getattribute__(cls.method) + return method(*arg, **varg) + spec.__class__.__call__ = call + else: + print("No module-calling avaiable, as co_names is empty") @classmethod def create_module(cls, spec): From 043363dad1213f1441936770965bbcaa171bdd86 Mon Sep 17 00:00:00 2001 From: Markus Vogl Date: Tue, 1 Oct 2019 22:56:13 +0200 Subject: [PATCH 3/3] Fix main --- README.rst | 5 ++--- main.py | 4 ++-- stackoverflow/__init__.py | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index c4393ce..25b990a 100644 --- a/README.rst +++ b/README.rst @@ -19,13 +19,12 @@ Let’s take it one step further. .. code:: pytho from stackoverflow import sort - print(sort.sort_iterable([3,1,2])) - >>> + print(sort([3,1,2])) print("I wonder who made sort", sort.__author__) print("but what's the license? Can I really use this?", sort.__license__) from stackoverflow import file_copy - print(file_copy.copyfile("main.py", "main2.py")) + print(file_copy("main.py", "main2.py")) """ prints [1, 2, 3] diff --git a/main.py b/main.py index 6220340..a978e9d 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,7 @@ from stackoverflow import sort -print(sort.sort_iterable([3,1,2])) +print(sort([3,1,2])) print("I wonder who made sort", sort.__author__) print("but what's the license? Can I really use this?", sort.__license__) from stackoverflow import file_copy -print(file_copy.copyfile("main.py", "main2.py")) \ No newline at end of file +print(file_copy("main.py", "main2.py")) \ No newline at end of file diff --git a/stackoverflow/__init__.py b/stackoverflow/__init__.py index b0f96ba..0445c21 100644 --- a/stackoverflow/__init__.py +++ b/stackoverflow/__init__.py @@ -30,7 +30,7 @@ def make_callable(cls, spec): methods = spec._code.co_names if methods: spec.__class__ = copy(spec.__class__) - spec.__class__.method = methods[0] + spec.__class__.method = methods[-1] # first methods can be imports like os, so take last! def call(cls, *arg, **varg): """ during find_spec, the method itself is not in cls -> dynamic calling """ method = cls.__getattribute__(cls.method)