I am trying to post to my pelican blog from another python app, so I am not doing pelican ./output -s settings.py from the commandline.
I have modified pelican to accept mocked argparse like object to pass what it needs, so I have moved the content of the main function in __init__.py
to function named runPelican(args) that accepts args, and from my app that has mocked Argparse like this,
class MockArgparse(object):
"""Mock for argparse's to pass to pelican
"""
def __init__(self, verbosity=True, theme=None, output=None, path=None, delete_outputdir=None,
settings=None, ignore_cache=None, cache_path=None, selected_paths=None, autoreload=None):
"""
Args:
path (str): content path
settings(str): settings python file path
"""
super(MockArgparse, self).__init__()
self.theme = theme
self.cache_path = cache_path
self.ignore_cache = ignore_cache
self.delete_outputdir = delete_outputdir
self.settings = settings
self.output = output
self.verbosity = verbosity
self.autoreload = autoreload
self.path = path
self.selected_paths = selected_paths
I am calling the runPelican from my python app like this:
if make_entry(args):
import pelican
arg = MockArgparse(path=CONTENT_PATH, theme=THEME_PATH, output=OUTPUT_PATH, settings=SETTINGS_PATH)
pelican.runPelican(arg)
Everything seems to go fine but the blog posts are not generated
and Only error I am getting is
CRITICAL: SimplerXMLGenerator instance has no attribute '_write'
any help would be greatly appreciated.
Related
Background:
I am writing a module in order to set-up an embedded system. In this context I need to load some modules and perform some system settings.
Context:
I have a parent class holding some general code (load the config file, build ssh connection etc.) used for several child classes. One of them is the module class that sets up the module and therefore uses among otherthings the ssh connection and the configuration file.
My goal is to share the configuration file and the connection with the next module, that will be setup. For the connection its just a waste to build and destroy it all the time, but for the configuration file, changes during setup can lead to undefined behavior.
Research/ approaches:
I tried using class variables, however they aren't passed when initaiting
a new module object.
Futher, I tried using global variables, but since the parent class and the
child classes are in different files, This won't work (Yes, i can put them
all in one file but this will be a mess) Also using a getter function from
the file where I defined the global variable didn't work.
I am aware of the 'builtin' solution from
How to make a cross-module variable?
variable, but feel this would be a bit of an overkill...
Finally, I can keep the config file and and the connection in a central
script and pass them to each of the instances, but this will lead to loads
of dependencies and I don't think it's a good solution.
So here is a bit of code with an example method, to get some file paths.
The code is set up according to approach 1 (class vaiables)
An example config file:
Files:
Core:
Backend:
- 'file_1'
- 'file_2'
Local:
File_path:
Backend: '/the/path/to'
The Parent class in setup_class.py
import os
import abc
import yaml
class setup(object):
__metaclass__ = abc.ABCMeta
configuration = []
def check_for_configuration(self, config_file):
if not self.configuration:
with open(config_file, "r") as config:
self.configuration = yaml.safe_load(config)
def get_configuration(self):
return self.configuration
def _make_file_list(self, path, names):
full_file_path = []
for file_name in names:
temp_path = path + '/' + file_name
temp_path = temp_path.split('/')
full_file_path.append(os.path.join(*temp_path))
return full_file_path
#abc.abstractmethod
def install(self):
raise NotImplementedError
The module class in module_class.py
from setup_class import setup
class module(setup):
def __init__(self, module_name, config_file = ''):
self.name = module_name
self.check_for_configuration(config_file)
def install(self):
self._backend()
def _backend(self):
files = self._make_file_list(
self.configuration['Local']['File_path']['Backend'],
self.configuration['Files'][self.name]['Backend'])
if files:
print files
And finally a test script:
from module_class import module
Analysis = module('Analysis',"./example.yml")
Core = module('Core', "./example.yml")
Core.install()
Now, when running the code, the config file is loaded everytime, a new module object is initaiated. I would like to avoid this. Are there approaches I have not considdered? What's the neatest way to achive this?
Save your global values in a global dict, and refer to that inside your module.
cache = {}
class Cache(object):
def __init__(self):
global cache
self.cache = cache
is there a way to configure test-config so that i can pass a URL in command line i.e. 'nosetests --tc=systest_url test_suit.py'
I need to run my selenium tests against dev and systest environments when performing builds on teamcity. Our team decided to use python for UI tests and Im more a Java guy and I'm tring to figure out how the plugin works it looks like i can store the url in yaml and pass the file to the --tc command but doesn't seem to work
the code i inherited looks like this :
URL = config['test' : 'https://www.google.com', ]
class BaseTestCase(unittest.TestCase, Navigation):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
cls.driver.implicitly_wait(5)
cls.driver.maximize_window()
cls.driver.get(URL)
which obviously is not working
There is a plugin for nose, the nosetest-config. You can specify some config file and pass filename to --tc-file arg from nose.
config.ini
[myapp_servers]
main_server = 10.1.1.1
secondary_server = 10.1.1.2
In your test file you can load the config.
test_app.py
from testconfig import config
def test_foo():
main_server = config['myapp_servers']['main_server']
Than, call nose with args
nosetests -s --tc-file example_cfg.ini
As described in docs, you can use other config files type like YAML, JSON or even Python modules.
Using the nose-testconfig --tc option you can override a configuration value. Separate the key from the value using a colon. For example,
nosetests test.py --tc=url:dev.example.com
will make the value available in config['url'].
from testconfig import config
def test_url_is_dev():
assert 'dev' in config['url']
I have here a Python program.
It uses CherryPy to create a server.
# coding:utf-8
import os.path
import cherrypy
from app import application
def main():
try:
currentDir_s = os.path.dirname(os.path.abspath(__file__))
except:
currentDir_s = os.path.dirname(os.path.abspath(sys.executable))
cherrypy.Application.currentDir_s = currentDir_s
configFileName_s = 'server.conf'
if os.path.exists(configFileName_s) == False:
configFileName_s = None
cherrypy.engine.autoreload.unsubscribe()
cherrypy.engine.timeout_monitor.unsubscribe()
cherrypy.quickstart(application.Application_cl(), config=configFileName_s)
if __name__ == '__main__':
main()
And in "server.conf" it configure the server:
[global]
tools.log_headers.on: True
tools.sessions.on: False
tools.encode.on: True
tools.encode.encoding:"utf-8"
server.socket_port: 8080
server.socket_timeout:60
server.thread_pool: 10
server.environment: "production"
log.screen: True
[/]
tools.staticdir.root: cherrypy.Application.currentDir_s
tools.staticdir.on = True
tools.staticdir.dir = '.'
There is one thing, I don't understand, this line (line 13 in the python code):
cherrypy.Application.currentDir_s = currentDir_s
I searched in the internet about this, but I couldn't find anything. What does "cherrypy.Application" do? Why I have to do this assignment (cherrypy.Application.currentDir_s = currentDir_s)?
I searched the cherrypy source code and here is what I found.
In _cptree.py module you will find the Application class. Below that, there is a Tree class which has mount method which we are used to binding applications with (e.g. cherrypy.tree.mount(Root(), "/", config=config))
def mount(self, root, script_name="", config=None):
...
When you look inside this method you will see the code below;
def mount(self, root, script_name="", config=None):
...
if isinstance(root, Application):
app = root
if script_name != "" and script_name != app.script_name:
raise ValueError(
"Cannot specify a different script name and pass an "
"Application instance to cherrypy.mount")
script_name = app.script_name
else:
app = Application(root, script_name)
# If mounted at "", add favicon.ico
if (script_name == "" and root is not None
and not hasattr(root, "favicon_ico")):
favicon = os.path.join(os.getcwd(), os.path.dirname(__file__),
"favicon.ico")
root.favicon_ico = tools.staticfile.handler(favicon)
if config:
app.merge(config)
self.apps[script_name] = app
So, the code says that every object (application) you pass to the mount method is either Application instance or wrapped in an Application instance. So why is that so? When you check Application class above Tree class, you will see a __call__ method like below;
def __call__(self, environ, start_response):
return self.wsgiapp(environ, start_response)
Yes you see it now, it is wsgi interface.
Therefore, Application is a wsgi wrapper for your cherrypy applications.
When you check the source code of cherrypy you may learn lots of things. I hope this answer help you.
In some source code I am
writing, I am able to make a request such as:
http://proxy.metaperl.org/index/bitgold-rw1
And have it redirect successfully.
However, I want to remove index from the URL and have it still
redirect by using the index() method. I tried renaming index() to
default() after reading about
Dispatching,
but it still does not allow me to have a URL like this:
http://proxy.metaperl.org/bitgold-rw1
It tries to find a method named bitgold-rw1 instead of using the
default method to resolve the request, gving me the error:
NotFound: (404, "The path '/bitgold-rw1' was not found.")
The WSGI startup file looks like this:
# -*- python -*-
# core
import os
import sys
# 3rd party
import cherrypy
# local
def full_path(*extra):
return os.path.join(os.path.dirname(__file__), *extra)
sys.path.insert(0, full_path())
import config
import myapp
application = cherrypy.Application(
myapp.Root(),
"/",
config.config)
As mentioned by #ralhei #saaj default method is the key if you do not want to deal with dispatchers in cherrypy. I tried the code below and working as you want
class Root(object):
#cherrypy.expose
def index(self, tag):
redirect_url = db.urls[tag]
ip = cherrypy.request.headers['Remote-Addr']
request_url = 'http://ipinfo.io/{0}/country'.format(ip)
r = requests.get(request_url)
country = r.text.strip()
raise cherrypy.HTTPRedirect(redirect_url)
#cherrypy.expose
def default(self,tag):
return self.index(tag)
Renaming to default is not enough. It needs to be callable at least with variadic arguments, *args, to receive path segments. Like this:
#!/usr/bin/env python3
import cherrypy
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
}
}
class Root:
#cherrypy.expose
def default(self, *args, **kwargs):
cherrypy.log('{0}, {1}'.format(args, kwargs))
return 'OK'
if __name__ == '__main__':
cherrypy.quickstart(Root(), '/', config)
Then it will catch things like http://127.0.0.1:8080/bitgold-rw1/ and also like http://127.0.0.1:8080/bitgold-rw1/foo/bar.
And btw, if it's about MVC it's a controller, not a view.
if you rename your index method to 'default' in your Root class this should work.
Add the line
cherrypy.quickstart(Root())
at the bottom of myapp.py and run it with 'python myapp.py' your server should startup and listen on port 8080.
Making a request to http://localhost:8080/bitgold-rw1 works for me, it complains that I'm not a US citizen which I guess is fine ;-)
from docutils.parsers.rst.directives.images import Figure
class MyFigure(Figure):
def run(self):
# here I need to read the 'thumbnails_folder' setting
pass
def setup(app):
app.add_config_value('thumbnails_folder', '_thumbnails', 'env')
How can I access the config value in .run()? I read sources of Sphinx-contrib, but did not see things done in my way, so they accessed conf.py the way I can't. Or should I do it in a different manner?
All I want to do is translate this
.. figure:: image/image.jpg
into this:
.. image:: image/thumbnails/image.jpg
:target: image/image.jpg
Here's the extension code
(the thumbnail is generated with PIL). And also put the :target: into downloadable files (As I see, only builder instances can do this).
The build environment holds a reference to the Config object. Configuration variables can be retrieved from this object:
def run(self):
env = self.state.document.settings.env # sphinx.environment.BuildEnvironment
config = env.config # sphinx.config.Config
folder = config["thumbnails_folder"]
...