failure to run a process from multiprocessing - flask

I have been trying to run a process when testing my browser app. The process is one of my fixture for pytest testing, and it should be running when i start my test. However, it showed error when i run it. I am quite confused because it should be a simple process. this is my code:
#pytest.fixture(scope='class')
def chrome_driver(request):
""" Selenium webdriver with options to support running in GitHub actions
Note:
For CI: `headless` and `disable-gpu` not commented out
For running on your computer: `headless` and `disable-gpu` to be commented out
"""
options = ChromeOptions()
#options.add_argument("--headless") # use for GitHub Actions CI
#options.add_argument('--disable-gpu') # use for GitHub Actions CI
options.add_argument("--window-size=1920,1080")
chrome_driver = Chrome(options=options)
request.cls.driver = chrome_driver
yield
chrome_driver.close()
#pytest.fixture(scope='class')
def run_app(app):
"""
Fixture to run the Flask app for Selenium browser tests
"""
multiprocessing.set_start_method("spawn") # Needed in Python 3.8 and later
#process = multiprocessing.Process(target=app.run, args=())
#process.start()
process = multiprocessing.Process(target=app.run, args=())
process.start()
process.join()
yield process
process.terminate()
above are the two fixtures for my testing, and they will be run the same time when i start my test. Below is the errors:
test setup failed
app = <Flask 'flask_app'>
#pytest.fixture(scope='class')
def run_app(app):
"""
Fixture to run the Flask app for Selenium browser tests
"""
multiprocessing.set_start_method("spawn") # Needed in Python 3.8 and later
#process = multiprocessing.Process(target=app.run, args=())
#process.start()
process = multiprocessing.Process(target=app.run, args=())
> process.start()
..\conftest.py:138:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\..\..\..\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py:121: in start
self._popen = self._Popen(self)
..\..\..\..\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py:224: in _Popen
return _default_context.get_context().Process._Popen(process_obj)
..\..\..\..\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py:327: in _Popen
return Popen(process_obj)
..\..\..\..\AppData\Local\Programs\Python\Python310\lib\multiprocessing\popen_spawn_win32.py:93: in __init__
reduction.dump(process_obj, to_child)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
obj = <Process name='Process-1' parent=26100 initial>
file = <_io.BufferedWriter name=11>, protocol = None
def dump(obj, file, protocol=None):
'''Replacement for pickle.dump() using ForkingPickler.'''
> ForkingPickler(file, protocol).dump(obj)
E AttributeError: Can't pickle local object 'Flask.__init__.<locals>.<lambda>'

I was able to get my similar test to run if I instead set multiprocessing.set_start_method("fork") and running the single test inside the IDE. As soon as I run it in a test suite I get the 'pickle' error though.

As Henry pointed out, forking will avoid the pickle error. Set in a session scoped fixture to executed once in pytest session.
#pytest.fixture(scope='session')
def init_multiprocessing():
multiprocessing.set_start_method("fork")
#pytest.fixture
def run_app(app, init_multiprocessing):
process = multiprocessing.Process(target=app.run)
process.start()
yield process
process.terminate()
process.join()

Related

Elixir Phoenix Serve S3 Image

I would like to request an S3 image and then serve it using Phoenix.
def getImage(conn, %{"id" => uuid}) do
file = ExAws.S3.get_object("bucket", "images/image.jpg")
|> ExAws.request
conn
|> put_resp_content_type("image/jpg")
|> put_resp_header(
"content-disposition",
"attachment; filename=\"file.jpg\""
)
|> send_resp(200, file)
end
I have found endless tutorials on how to upload to S3 but nothing on retrieving. Thank you in advance!
You have to pattern match against get_object function and extract image content from that.
def getImage(conn, %{"id" => uuid}) do
{:ok, %{body: image_content}} = ExAws.S3.get_object("bucket", "images/image.jpg")
|> ExAws.request
conn
|> put_resp_content_type("image/jpg")
|> put_resp_header(
"content-disposition",
"attachment; filename=\"file.jpg\""
)
|> send_resp(200, image_content)
end

Checking each URL works in tests on a Yesod site

I was trying to check that all links work on a Yesod website home page. I wrote this hSpec test.
module Handler.HomeSpec (spec) where
import Data.Either (fromRight)
import qualified Data.Text as T
import Network.Wai.Test (simpleBody)
import TestImport
import Yesod.Test.TransversingCSS (findAttributeBySelector)
getAllLinks :: YesodExample site [Text]
getAllLinks = withResponse $ \res -> do
let links = fromRight [] findAttributeBySelector (simpleBody res) "a" "href"
return $ T.concat <$> links
spec :: Spec
spec = withApp $
describe "Homepage" $ do
it "checks all links" $ do
get HomeR
statusIs 200
links <- getAllLinks
forM_ links $ \oneLink -> do
get HomeR
statusIs 200
get oneLink
statusIs 200
Everything compiles ok but the get function gets rid of the host part of the URLs you feed it. For example, when you give it https://github.com/zigazou/bazasso, it will try to fetch /zigazou/bazasso which returns a 404 code.
Is there a way to make it work like I want ?
Should I add a function that removes external links from the tests ?
Is it simply not the right place to do it ?
The simpler, the better: I've removed everything that starts with a protocol from the links that will be checked. Thanks to #ncaq for your comments.
module Handler.HomeSpec (spec) where
import Data.Either (fromRight)
import qualified Data.Text as T
import Network.Wai.Test (simpleBody)
import TestImport
import Yesod.Test.TransversingCSS (findAttributeBySelector)
isRelative :: Text -> Bool
isRelative url
| T.take 7 url == "http://" = False
| T.take 8 url == "https://" = False
| T.take 7 url == "mailto:" = False
| T.take 4 url == "tel:" = False
| otherwise = True
getAllLinks :: YesodExample site [Text]
getAllLinks = withResponse $ \res -> do
let currentHtml = simpleBody res
links = fromRight [] $ findAttributeBySelector currentHtml "a" "href"
return $ filter isRelative $ T.concat <$> links
spec :: Spec
spec = withApp $
describe "Homepage" $ do
it "checks all links" $ do
get HomeR
statusIs 200
links <- getAllLinks
forM_ links $ \oneLink -> do
get HomeR
statusIs 200
get oneLink
statusIs 200

pytest django: unable to access db in fixture teardown

I need to explicitly delete a fixture after it is used. I know that pytest-django by default drops all objects on teardown but in this particular case I need to do it manually. However, although my tests are marked as pytest.mark.django_db, I am able to create a fixture, but unable to delete it after a yield line:
import pytest
from tgapps.models import TelegramApp
#pytest.fixture(scope='module')
def some_fixture():
app = TelegramApp.objects.create(
session_data=b'\xa2\x8f#',
app_owner_phone=79856235474,
app_id=182475,
app_hash='aad9ab4384fea1af0342b77b606d13b0'
)
yield app
print('deleting object...')
app.delete()
class TestTelegramServiceObject(object):
#pytest.mark.django_db
def test1(self, some_fixture):
print('Fixture created:')
print(some_fixture)
this is my test output:
============================= test session starts ==============================
platform darwin -- Python 3.6.4, pytest-3.4.0, py-1.5.2, pluggy-0.6.0
Django settings: inviter.settings.staging (from ini file)
rootdir: /Users/1111/_projects/fasttrack/inviter, inifile: pytest.ini
plugins: mock-1.7.1, dotenv-0.1.0, django-3.1.2
collected 1 item
test_example.py E.Fixture created:
<79856235474 - 182475>
deleting object...
tests/api/test_example.py:25 (TestTelegramServiceObject.test1)
#pytest.fixture(scope='module')
def some_fixture():
app = TelegramApp.objects.create(
session_data=b'\xa2\x8f#',
app_owner_phone=79856235474,
app_id=182475,
app_hash='aad9ab4384fea1af0342b77b606d13b0'
)
yield app
print('deleting object...')
> app.delete()
test_example.py:21:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/base.py:890: in delete
collector.collect([self], keep_parents=keep_parents)
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/deletion.py:221: in collect
elif sub_objs:
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:276: in __bool__
self._fetch_all()
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:1179: in _fetch_all
self._result_cache = list(self._iterable_class(self))
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:53: in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/sql/compiler.py:1062: in execute_sql
cursor = self.connection.cursor()
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/backends/base/base.py:255: in cursor
return self._cursor()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0x1048bf080>
name = None
def _cursor(self, name=None):
> self.ensure_connection()
E Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
Why is this? and how do I enable DB assess on fixture teardown?
The db fixture as mentioned by Andreas Profous is function scoped so that wouldn't work here.
What you need to do is:
#pytest.fixture(scope='module')
def some_fixture(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
app = TelegramApp.objects.create(
session_data=b'\xa2\x8f#',
app_owner_phone=79856235474,
app_id=182475,
app_hash='aad9ab4384fea1af0342b77b606d13b0'
)
yield app
with django_db_blocker.unblock():
print('deleting object...')
app.delete()
django_db_setup ensures the test database is setup (and ready) for additional records to be added. django_db_blocker is what the db fixture uses to allow function scoped modifications. The reason why it's function scoped is so that it will behave how TestCase methods behave in the default unittest framework where the records are rolled back after each test. This is a good thing, it ensures a modification of a record in one test won't change the outcome in other test.
So be very careful when creating fixtures that aren't function scoped as your modifications won't by default be wrapped in a transaction and rolled back. Using the django_db_blocker gives you hooks into the django_db_blocker.unblock() method which removes the block from modifying the database. This is required in your non-function scoped fixtures.
You need to require the db fixture in some_fixture:
def some_fixture(db):
...

Use OUnit module in OCaml - Unbound module OUnit error

I'm trying to use OUnit with OCaml.
The unit code source (unit.ml) is as follows:
open OUnit
let empty_list = []
let list_a = [1;2;3]
let test_list_length _ =
assert_equal 1 (List.length empty_list);
assert_equal 3 (List.length list_a)
(* etc, etc *)
let test_list_append _ =
let list_b = List.append empty_list [1;2;3] in
assert_equal list_b list_a
let suite = "OUnit Example" >::: ["test_list_length" >:: test_list_length;
"test_list_append" >:: test_list_append]
let _ =
run_test_tt_main suite
With ocamlc unit.ml, I got an error message Error: Unbound module OUnit. Why is this? How can I use the OUnit in OCaml. I installed OUnit with opam.
You should use for example:
ocamlfind ocamlc -package oUnit -linkpkg -o unit unit.ml
ocamlfind is an utility that encapsulates lookup of installed libraries. You can also avoid composing compiler-invocation yourself and use a build tool.

Scripted main in OCaml?

How can I emulate this Python idiom in OCaml?
if __name__=="__main__":
main()
See RosettaCode for examples in other programming languages.
There is no notion of main module in Ocaml. All the modules in a program are equal. So you can't directly translate this Python idiom.
The usual way in Ocaml is to have a separate file containing the call to main, as well as other stuff like command line parsing that only make sense in a standalone executable. Don't include that source file when linking your code as a library.
There is a way to get at the name of the module, but it's rather hackish, as it is intended for debugging only. It violates the usual assumption that you can rename a module without changing its behavior. If you rely on it, other programmers reading your code will curse you. This method is provided for entertainment purposes only and should not be used in real life.
let name_of_this_compilation_unit =
try assert false with Assert_failure (filename, _, _) -> filename
You can compare the name of the compilation unit with Sys.executable_name or Sys.argv.(0). Note that this is not really the same thing as the Python idiom, which does not rely on the toplevel script having a particular name.
$ ocamlc -o scriptedmain -linkall str.cma scriptedmain.ml
$ ./scriptedmain
Main: The meaning of life is 42
$ ocamlc -o test -linkall str.cma scriptedmain.ml test.ml
$ ./test
Test: The meaning of life is 42
scriptedmain.ml:
let meaning_of_life : int = 42
let main () = print_endline ("Main: The meaning of life is " ^ string_of_int meaning_of_life)
let _ =
let program = Sys.argv.(0)
and re = Str.regexp "scriptedmain" in
try let _ = Str.search_forward re program 0 in
main ()
with Not_found -> ()
test.ml:
let main () = print_endline ("Test: The meaning of life is " ^ string_of_int Scriptedmain.meaning_of_life)
let _ =
let program = Sys.argv.(0)
and re = Str.regexp "test" in
try let _ = Str.search_forward re program 0 in
main ()
with Not_found -> ()
Posted on RosettaCode.