Scan a directory to load Python plugin from C++ - c++

I want to make a C++ application that can handle both C++ and Python plugin. For the C++ part i'm fine, but I have questions about Python plugins.
What I want to do, is to have a directory with all my python plugins, and the application will load all plugins located in this directory (like Sublime Text 2).
My problem is that I don't know how to "parse" a python script to get the name of every class that inherits from my plugin interface in order to create them.
Is there a way in boost.python to do that ? (I haven't found informations about it)
Does python have module variable I can use to do this ? (I'm not so
good with python)
Do I need to use a lexer like antlr ? ( seems heavy ...)
Do I need to have a "create" function like in C++ ? (Sublime Text
2 don't seems to need that)
Finally, do you know C++ application that handle Python plugin where I can check the code ?
Thanks ;)

This question is a bit loaded/unclear, but I'll give it a shot.
My problem is that I don't know how to "parse" a python script to get the name of every class that inherits from my plugin interface in order to create them.
This can be done somewhat easily with a python script; perhaps you can write one and call it from your C++ application. Here is a snippet of code that finds python scripts '*.py', imports them, and looks for classes that subclass a class called PluginInterface... not sure what you need to do after that, so I put a TODO there.
def find_plugins(directory):
for dirname, _, filenames in os.walk(directory): # recursively search 'directory'
for filename in filenames:
# Look for files that end in '.py'
if (filename.endswith(".py")):
# Assume the filename is a python module, and attempt to find and load it
### need to chop off the ".py" to get the module_name
module_name = filename[:-3]
# Attempt to find and load the module
try:
module_info = imp.find_module(module_name, [dirname])
module = imp.load_module(module_name, *module_info)
# The module loaded successfully, now look through all
# the declarations for an item whose name that matches the module name
## First, define a predicate to filter for classes from the module
## that subclass PluginInterface
predicate = lambda obj: inspect.isclass(obj) and \
obj.__module__ == module_name and \
issubclass(obj, PluginInterface)
for _, declaration in inspect.getmembers(module, predicate):
# Each 'declaration' is a class defined in the module that inherits
# from 'PluginInterface'; you can instantiate an object of that class
# and return it, print the name of the class, etc.
# TODO: fill this in
pass
except:
# If anything goes wrong loading the module, skip it quietly
pass
Perhaps this is enough to get you started, although it's not really complete, and you'll probably want to understand all the python libraries being used here so you can maintain this in the future.

Related

Multiple Transforms for VSCode Snippet

I've got a few snippets set up and working as I would like to, but I'm having a hard time getting one snippet to work where I believe I will need to have multiple transforms occur?
Essentially I have a TypeScript Interface defined for one of my components.
i.e. IRadioButtonListProps.ts which is inside of an Interfaces folder. The Interfaces folder has a sibling folder named Theme containing an interface named IRadioButtonListTheme.ts
Inside of IRadioButtonListProps I'm trying to stub out the entire interface. The snippet I currently have stubs out the interface like...
import * as React from 'react';
import IRadioButtonListPropsTheme from '../Theme/IRadioButtonListPropsTheme';
export interface IRadioButtonListPropsProps {
...props...
}
export default IRadioButtonListPropsProps;
The import line inside of the snippet is...
"import I${TM_FILENAME_BASE/(.*)\\..+$/$1/}Props from './Interfaces/I${TM_FILENAME_BASE/(.*)\\..+$/$1/}Props';"
What I'm trying to have happen and can't seem to figure out is how to also remove the word "Props". So instead of import IRadioButtonListPropsTheme... I would get import import IRadioButtonListTheme....
At the same time, I want to remove all extensions, including those of the form *.abc.abc ("two" extensions) and *.abc (one simple extension).
Is this possible?
It isn't crystal clear what you what but try:
"import ${TM_FILENAME/((\\w*)Props)*?(\\..*)/$2/}Theme from './Interfaces/${TM_FILENAME/((\\w*)Props)*?(\\..*)/$2/}Theme';"
which results in:
import IRadioButtonListTheme from './Interfaces/IRadioButtonListTheme';
from IRadioButtonListProps.ts
and
import CheckboxListTheme from './Interfaces/CheckboxListTheme';
from CheckboxListProps.test.tsx
[Edit] Here is a simpler version which I think also works:
"import ${TM_FILENAME/(Props)*?(\\..*)//}Theme from './Interfaces/${TM_FILENAME/(Props)*?(\\..*)//}Theme';"
match any "Props", if any, replace with nothing.
match from first \. to end of filename, replace with nothing.

Flask Babel: adding pycountry external locale

I am trying to add an external locale directory from the pycountry package.
Before initializing Flask Babel, I do the following:
import pycountry
app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'translations;' + pycountry.LOCALES_DIR
But alas, this does not seem to be enough. For example, gettext('Germany') will not find the translation.
I think the problem might be how translations are structured in pycountry.
~/.local/lib/python3.5/site-packages/pycountry/locales/pt/LC_MESSAGES$ ls
iso15924.mo iso3166-3.mo iso4217.mo iso639-3.mo
iso3166-1.mo iso3166.mo iso639_3.mo
Do I need to specify I want, e.g., the iso3166 file? Please see the following reference.
Reference: pycountry locale documentation section
I also needed to load pycountry locale with flask babel.
To do that, I look into flask-babel get_translations() about how they load translations.
Anyway, I have something working putting this somewhere in your app.
def hack_country_gettext(string):
translations = support.Translations()
catalog = translations.load(pycountry.LOCALES_DIR, [get_locale()], 'iso3166')
translations.merge(catalog)
return translations.ugettext(string)
and instead of _('Germany') use the hack function hack_country_gettext('Germany')

How to install LaTeX class on Heroku?

I have a Django app hosted on Heroku. In it, I am using a view written in LaTeX to generate a pdf on-the-fly, and have installed the Heroku LaTeX buildpack to get this to work. My LaTeX view is below.
def pdf(request):
context = {}
template = get_template('cv/cv.tex')
rendered_tpl = template.render(context).encode('utf-8')
with tempfile.TemporaryDirectory() as tempdir:
process = Popen(
['pdflatex', '-output-directory', tempdir],
stdin=PIPE,
stdout=PIPE,
)
out, err = process.communicate(rendered_tpl)
with open(os.path.join(tempdir, 'texput.pdf'), 'rb') as f:
pdf = f.read()
r = HttpResponse(content_type='application/pdf')
r.write(pdf)
return r
This works fine when I use one of the existing document classes in cv.tex (eg. \documentclass{article}), but I would like to use a custom one, called res. Ordinarily I believe there are two options for using a custom class.
Place the class file (res.cls, in this case) in the same folder as the .tex file. For me, that would be in the templates folder of my app. I have tried this, but pdflatex cannot find the class file. (Presumably because it is not running in the templates folder, but in a temporary directory? Would there be a way to copy the class file to the temporary directory?)
Place the class file inside another folder with the structure localtexmf/tex/latex/res.cls, and make pdflatex aware of it using the method outlined in the answer to this question. I've tried running the CLI instructions on Heroku using heroku run bash, but it does not recognise initexmf, and I'm not entirely sure how to specify a relevant directory.
How can I tell pdflatex where to find to find the class file?
Just 2 ideas, I don't know if it'll solve your problems.
First, try to put your localtexmf folder in ~/texmf which is the default local folder in Linux systems (I don't know much about Heroku but it's mostly Linux systems, right?).
Second, instead of using initexmf, I usually use texhash, it may be available on your system?
I ended up finding another workaround to achieve my goal, but the most straightforward solution I found would be to change TEXMFHOME at runtime, for example...
TEXMFHOME=/d pdflatex <filename>.tex
...if you had /d/tex/latex/res/res.cls.
Credit goes to cfr on tex.stackexchange.com for the suggestion.

Module cannot be resolved from lib in Rails

If I write a class in a file in lib, I can find it. If I write a module in the same file, I cannot find it. Did I miss something?
The files look like:
And the file contents are:
class Cool
end
module Flags
Countries = []
end
If I try to call them from a controller:
class MainController < ApplicationController
def index
Cool.new # works
Flags::Countries # uninitialized constant MainController::Flags
end
end
Might not a solution to your specific scenario, just a few relevant points:
Rails autoloading expects classes / modules to follow namespacing rules:
Flags::Countries -> <autoload paths>/flags/countries.rb
http://urbanautomaton.com/blog/2013/08/27/rails-autoloading-hell/
Don't think /lib/ is a standard autoloading path, so you'll need to ensure it's added into your path.

Testing a python recipe

I want to run a python recipe I found, but I don't know how as it imports from another one!
For example, I would like to test the code here.
I have downloaded it and also downloaded this one as it uses it.
So how can I test the this code by passing the needed parameter as below?!
>>> G = {'s':{'u':10, 'x':5}, 'u':{'v':1, 'x':2}, 'v':{'y':4}, 'x':{'u':3, 'v':9, 'y':2}, 'y':{'s':7, 'v':6}}
>>> Dijkstra.Dijkstra(G,'s','v')
I have added the two files in one of the python paths, and imported both but still get error
Could you please give me some advice on simple way to test this code?
You really should put the files in your current directory if you are just testing, instead of putting them in /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ as that path is reserved for the Python standard library.
It seems that the second recipe, the Priority Dictionary, needs to be put in a file called priodict.py since the Dijkstra code imports from priodict. So, you should have the following files in your current directory: Dijkstra.py, priodict.py. Then you can just start Python and do import Dijkstra, and it should work.
Also, don't modify the Dijkstra code to remove the import as you apparently did...