Fastapi - How to override BaseSettings of my library - fastapi

I have an app with these settings:
class Settings(BaseSettings):
local: str = "test"
settings = Settings()
I have a library that is imported to the app:
class Settings(BaseSettings):
local: str = "no_local_set"
settings = Settings()
When i print local in my app it's print me 'no_local_set'. There is a way to override BaseSettings in my main app, and this settings will be use everywhere on my librairies.
My main purpose here is the lib will be use in many different app. So the 'local' variable will be different depending of app that use the library.

In your main you could solve it like this:
#import Settings from <libaryname>
class MainSettings(Settings):
def __init__(self):
self.local = "test"
settings = MainSettings()
Now you've overwritten the Settings class and added specific settings.
I would remove
settings = Settings()
from your library.

Related

Error: RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret

I'm trying to deploy my flask application on Ubuntu 20.04 using Nginx and Gunicorn. It's been working smoothly when I run FLASK_APP=run.py and then gunicorn -w 9 run=app. However when I setup the configuration files for gunicorn and a config.py I was only able to access the home page but every other route results in an Internal Sever Error.
I set my log file to /var/log/app_name/app_name.err.log. The error reported in the logs is raise RuntimeError( RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret. .
Here is a copy of my config.py which is inside my application module where routes.py,models.py and forms.py are.
import os
import json
with open('/etc/scheye_config.json') as config_file:
config = json.load(config_file)
class Config:
SECRET_KEY = config.get('SECRET_KEY')
SQL_ALCHEMY_DATABASE_URI = config.get('SQL_ALCHEMY_DATABASE_URI')
MAIL_SERVER = config.get('MAIL_SERVER')
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USERNAME = config.get('EMAIL_USER')
MAIL_PASSWORD = config.get('APPLICATION_PASS')
As you can see I'm importing the settings from my json.config file whose code is shown below. The location for the json file is /etc/app_name.json.
{
"SECRET_KEY": "mysecretkey",
"SQLALCHEMY_DATABASE_URI": "database_uri",
"EMAIL_USER": "mymail#mail.com",
"APPLICATION_PASS": "application_password",
"MAIL_SERVER": "smtp.servermail.com"
}
In my init.py also has almost the same configurations only that I use environment variables. Here's a copy of the init.py.
import os
from flask import Flask
from sqlalchemy.orm import backref
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager, login_manager
from flask_mail import Mail
from sqlalchemy import create_engine
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
# configuring the database using SQLAlchemy
ENV = 'dev'
if ENV == 'dev':
app.debug=True
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('SQLALCHEMY_DATABASE_URI')
else:
app.debug=False
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('SQLALCHEMY_DATABASE_URI')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager= LoginManager(app)
login_manager.login_view='login' #
login_manager.login_message_category='info' #styling the message returned
app.config['MAIL_SERVER'] = os.environ.get('MAIL_SERVER')
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME']= os.environ.get('EMAIL_USER')
app.config['MAIL_PASSWORD']= os.environ.get('APPLICATION_PASS')
#initializing our extension
mail = Mail(app)
engine = create_engine('database_uri')
connection = engine.raw_connection()
cursor = connection.cursor()
from app_name import routes
I have intentionally set my SQLALCHEMY_DATABASE_URI in order to continue testing the app before creating a production database.
I've gone through Configuration Handling in the flask documentation 2.2x and tried possible solutions but to no success. Being quite new to deployment I fear the answer is quite obvious and the source of the error is in the numerous configuration files. If anyone understands what the issue is I would highly appreciate his/her help.
in init.py you do not use your config module
try loading your base config, after app = Flask(__name__)
app.config.from_object('config.Config')
but if you haven't SECRET_KEY in env vars then SECRET_KEY will None again
then remove app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
or use it in Config class for SECRET_KEY definition as:
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY', config.get('SECRET_KEY'))

Tomcat 8 webapp, dynamically add PostResources

I have a webapp which uses a listener to dynamically add servlet instances.
Each servlet instance is defined by a user-defined configuration files, and encapsulates a distinct dataset. Each of these datasets may also include some user-defined static web files (HTML, JPG, CSS etc).
The static resources for each servlet instance are stored outside the webapp folder (to avoid deletion on redeployment), and each servlet instance has a separate folder hierarchy.
In the listener contextInitialized method, I am using
javax.servlet.ServletContext.addServlet
to add each of my servlet instances, and
javax.servlet.ServletRegistration.Dynamic.addMapping
to add the URL mapping for this servlet.
I would like to add other mappings for the static content in external folders.
In Tomcat 7, I extended org.apache.catalina.servlets.DefaultServlet
to change the relativePath to my new document root, but this class
does not work in Tomcat 8 0 - ClassNotFoundException (org.apache.naming.resources.FileDirContext).
Tomcat 8 has a new 'Resources' framework which should make this much more straightforward.
My question is - how can I add a PostResources element to my context dynamically (at web app startup, inside my listener), without editing the web.xml?
In my listener, I should be able to do something like this:
WebResourceRoot root = new StandardRoot(context);
root.createWebResourceSet(WebResourceRoot.ResourceSetType.POST,
"/my/url", "my/filesystem/path", null, "/");
but I cannot figure out how to get the required context (org.apache.catalina.Context), which is a completely different type to the similarly named javax.servlet.ServletContext provided by the ServletContextEvent in the listener contextInitialized method.
Any suggestions?
Thanks.
I think I have figured it out using the MBeanServer.
This seems a bit of a roundabout method though - is there no way of getting to the StandardRoot or StandardContext object from the ServletContext?
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.servlet.ServletContext;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.Container;
import org.apache.catalina.Server;
import org.apache.catalina.Service;
import org.apache.catalina.WebResourceRoot;
...
private void addPostResources(ServletContext servletContext)
throws Exception /* just for debugging */ {
MBeanServer mbs = MBeanServerFactory.findMBeanServer(null).get(0);
ObjectName name = new ObjectName("Catalina","type","Server");
Server server = (Server)mbs.getAttribute(name, "managedResource");
Service service = server.findService("Catalina");
StandardEngine engine = service.getContainer();
Container hostContainer = engine.findChild(engine.getDefaultHost());
StandardContext standardContext = (StandardContext)hostContainer.findChild(servletContext.getContextPath());
WebResourceRoot root = standardContext.getResources();
root.createWebResourceSet(WebResourceRoot.ResourceSetType.POST,
"/my/url", "my/filesystem/path", null, "/");
}

Resolve artifact with sbt programmatically

The following blog propose how to fetch an artifact directly from java using ivy (http://developers-blog.org/blog/default/2010/11/08/Embed-Ivy-How-to-use-Ivy-with-Java).
public class IvyArtifactResolver {
public File resolveArtifact(String groupId, String artifactId, String version) throws Exception {
//creates clear ivy settings
IvySettings ivySettings = new IvySettings();
//url resolver for configuration of maven repo
URLResolver resolver = new URLResolver();
resolver.setM2compatible(true);
resolver.setName("central");
//you can specify the url resolution pattern strategy
resolver.addArtifactPattern(
"http://repo1.maven.org/maven2/"
+ "[organisation]/[module]/[revision]/[artifact](-[revision]).[ext]");
//adding maven repo resolver
ivySettings.addResolver(resolver);
//set to the default resolver
ivySettings.setDefaultResolver(resolver.getName());
//creates an Ivy instance with settings
Ivy ivy = Ivy.newInstance(ivySettings);
File ivyfile = File.createTempFile("ivy", ".xml");
ivyfile.deleteOnExit();
String[] dep = null;
dep = new String[]{groupId, artifactId, version};
DefaultModuleDescriptor md =
DefaultModuleDescriptor.newDefaultInstance(ModuleRevisionId.newInstance(dep[0],
dep[1] + "-caller", "working"));
DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md,
ModuleRevisionId.newInstance(dep[0], dep[1], dep[2]), false, false, true);
md.addDependency(dd);
//creates an ivy configuration file
XmlModuleDescriptorWriter.write(md, ivyfile);
String[] confs = new String[]{"default"};
ResolveOptions resolveOptions = new ResolveOptions().setConfs(confs);
//init resolve report
ResolveReport report = ivy.resolve(ivyfile.toURL(), resolveOptions);
//so you can get the jar library
File jarArtifactFile = report.getAllArtifactsReports()[0].getLocalFile();
return jarArtifactFile;
}
}
I'm wondering if sbt exposes this kind of interface since it uses ivy.
resolve :: ModuleId -> File
Scripts, REPL, and Dependencies
There's a document called Scripts, REPL, and Dependencies you might be interested in. Script runner for example lets you write something like this:
#!/usr/bin/env scalas
!#
/***
scalaVersion := "2.9.0-1"
libraryDependencies ++= Seq(
"net.databinder" %% "dispatch-twitter" % "0.8.3",
"net.databinder" %% "dispatch-http" % "0.8.3"
)
*/
import dispatch.{ json, Http, Request }
import dispatch.twitter.Search
driving sbt programmatically
You can also use any subparts of sbt as a library and drive it yourself. Because of the plugin ecosystem, it's pretty good about maintaining binary compatibility among the point releases. The key task that grabs jars would be update, so def updateTask (Defaults.scala#L1113) could be a good place to start. If you are driving sbt from the client code, however, wouldn't you end up re-implementing sbt shell or including all the sbt's dependencies? You might as well have a separate sbt shell window or sbt script section.
Custom Resolvers
sbt ships with variety of customizable resolvers, so the first place to check out should be: Resolvers:
sbt provides an interface to the repository types available in Ivy: file, URL, SSH, and SFTP. A key feature of repositories in Ivy is using patterns to configure repositories.
Construct a repository definition using the factory in sbt.Resolver for the desired type. This factory creates a Repository object that can be further configured. The following table contains links to the Ivy documentation for the repository type and the API documentation for the factory and repository class. The SSH and SFTP repositories are configured identically except for the name of the factory. Use Resolver.ssh for SSH and Resolver.sftp for SFTP.
For example you can do:
resolvers += Resolver.file("my-test-repo", file("test")) transactional()
RawRepository
But if you truly want a programmable resolver, there is RawRepository:
final class RawRepository(val resolver: DependencyResolver) extends Resolver
{
def name = resolver.getName
override def toString = "Raw(" + resolver.toString + ")"
}
This is a thin wrapper around org.apache.ivy.plugins.resolver.DependencyResolver, which you should be able to write by extending one of the resolvers they have. (I haven't tried this myself.)

How to restrict image file extension on Plone?

I have a Plone application in which I can upload images, which are ATImages. I want to validate the extension file (mainly to forbid pdf files). There are created with a url call like http://blablba.com/createObject?type_name=Image
I have tried setting the /content_type_registry with file extensions associated with images, with no success (pdf upload still work)
I guess I could write a new class extending ATImages, create a form with a validator, but it looks a little bit complicated and it seemed that some settings on content_type registry would be enough (or elsewhere).
How would you do that ? (forbid pdf ?)
thx
We had a similar problem.
Archetypes fires several events during its magic, amongst others a "post validation event" (IObjectPostValidation). This way we added a check for the content-type.
subscriber (zcml):
<subscriber provides="Products.Archetypes.interfaces.IObjectPostValidation"
factory=".subscribers.ImageFieldContentValidator" />
quick and dirty implementation:
from Products.Archetypes.interfaces.field import IImageField
from plone.app.blob.interfaces import IBlobImageField
from Products.Archetypes.interfaces import IObjectPostValidation
from zope.interface import implements
from zope.component import adapts
# import your message factory as _
ALLOWED_IMAGETYPES = ['image/png',
'image/jpeg',
'image/gif',
'image/pjpeg',
'image/x-png']
class ImageFieldContentValidator(object):
"""Validate that the ImageField really contains a Imagefile.
Show a Errormessage if it doesn't.
"""
implements(IObjectPostValidation)
adapts(IBaseObject)
img_interfaces = [IBlobImageField, IImageField]
msg = _(u"error_not_image",
default="The File you wanted to upload is no image")
def __init__(self, context):
self.context = context
def __call__(self, request):
for fieldname in self.context.Schema().keys():
field = self.context.getField(fieldname)
if True in [img_interface.providedBy(field) \
for img_interface in self.img_interfaces]:
item = request.get(fieldname + '_file', None)
if item:
header = item.headers
ct = header.get('content-type')
if ct in ALLOWED_IMAGETYPES:
return
else:
return {fieldname: self.msg}

MinimalComps Flash GUI and Transcoding Errors

Basically, irrespective of what changes I make to my source, compiling alway yields either a transcoding error, or a missing definition.
I'm new to flash so it's difficult for me to understand how to go about fixing the problem.
Anyway here is the source.
The stack overflow link I always put in all my source, to look at for encouragement every time I feel like banging my head against the keyboard.
// Main.as
package
{
// General imports
// http://stackoverflow.com/questions/564756/should-i-just-give-up-on-programming
import com.bit101.components.Label;
import flash.display.*;
import flash.events.*;
import AssetManager;
// Begin external facing class
public class Main extends Sprite
{
public function Main()
{
var globalFont:String = AssetManager.FONT_PFRONDA;
//var myLabel:com.bit101.components.Label = new Label(Main = null, xpos = 25, ypos = 30, text = "Test Successfull");
//addChild(myLabel);
}
}
---
// AssetManager.as
package
{
public class AssetManager
{
[Embed(source = 'C:\\Documents and Settings\\Geko\\Desktop\\Flash\\testclient\\lib\\MinimalComps_0_9_5_\\src\\assets\\pf_ronda_seven.ttf', fontName = 'PF Ronda Seven', fontWeight = 'normal', advancedAntiAliasing = 'true', mimeType = 'application/x-font-truetype')] public static const FONT_PFRONDA:String;
}
}
Currently when I try to compile I get the following error...
C:\Documents and Settings\Geko\Desktop\Flash\testclient\src\Main.as(6): col: 31
Error: Definition com.bit101.components:Label could not be found.
and if I remove the comment from "var myLabel" or "addChild lines" in Main.as, then I get..
C:\Documents and Settings\Geko\Desktop\Flash\testclient\lib\MinimalComps_0_9_5_\src\com\bit101\components\Component.as(51): col: 4: Error: transcoding parameter 'embedAsCFF' is not supported by 'flex2.compiler.media.FontTranscoder'
C:\Documents and Settings\Geko\Desktop\Flash\testclient\lib\MinimalComps_0_9_5_\src\com\bit101\components\Component.as(51): col: 4: Error: Unable to transcode /assets/pf_ronda_seven.ttf.
My classpaths are "src", "lib\MinimalComps_0_9_5_\src\assets", and "lib\MinimalComps_0_9_5_\src\com\bit101\components"
I'm using Flex SDK 3.5.0.12683 on Windows XP with FlashDevelop 3.2.1 RTM
Any ideas as to why I'm constantly receiving errors each time I try to build the project?
C:\Documents and Settings\Geko\Desktop\Flash\testclient\src\Main.as(6): col: 31 Error: Definition com.bit101.components:Label could not be found.
this would suggest that the application can't find the Label class, possible reasons could be a problem with your classes library path, not importing the Label class, problem with the Label class package name etc...
The other two errors have to do with the way your font is embed. "embedAsCFF" requires Flex SDK 4.
In the error message you get a mention to the flex2 compiler.
'flex2.compiler.media.FontTranscoder'
Are you sure to be using the Flex SDK 3.5? I don't use FlashDevelop myself , so I wouldn't know where to look in order to edit the current Flex SDK.

Resources