Python Cerberus dependencies on nested list level - cerberus

Does Cerberus 1.2 support dependency validation on a list?
For instance the schema looks as follows:
schema = {
'list_1': {
'type': 'list',
'schema': {
'type': 'dict',
'schema': {
'simple_field': {'type': 'boolean'},
'not_simple_field': {
'type': 'dict',
'schema': {
'my_field': {'dependencies': {'simple_field': True}}
}
}
}
}
}
}
The rule that I'd like to check is that my_field should only exist when simple_field is True. How would I translate that in Cerberus?

As of now Cerberus 1.2 does not support this feature. I've overridden the Validator class method _lookup_field in order to implement this functionality.
Here's the link to a feature request on GitHub
Here's my implementation:
def _lookup_field(self, path: str) -> Tuple:
"""
Implement relative paths with dot (.) notation as used
in Python relative imports
- A single leading dot indicates a relative import
starting with the current package.
- Two or more leading dots give a relative import to the parent(s)
of the current package, one level per dot after the first
Return: Tuple(dependency_name: str, dependency_value: Any)
"""
# Python relative imports use a single leading dot
# for the current level, however no dot in Cerberus
# does the same thing, thus we need to check 2 or more dots
if path.startswith('..'):
parts = path.split('.')
dot_count = self.path.count('.')
context = self.root_document
for key in self.document_path[:dot_count]:
context = context[key]
context = context.get(parts[-1])
return parts[-1], context
else:
return super()._lookup_field(path)

Related

Rails 6 warning: Overwriting existing method <model_name>.fetched_state

Rails 6.0.2.1
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
my ArticleDir class has 2 scopes:
scope :active, -> { where(active: true).where(expired_on: nil) }
scope :fetched_state, -> { where(state: ArticleDir::FETCHED.to_s) }
and a function:
def article_engine_counts(keyword_reln = Keyword.active_keywords)
joins(:keywords, :article_engine)
.where(Keyword.contains(keyword_reln))
.where(self.table[:active].eq(true))
.group(:state, ArticleEngine.table[:name]).count
end
On running the function in rails console, I get:
irb(main):108:0> ArticleDir.article_engine_counts(keyword)
Creating scope :active. Overwriting existing method ArticleDir.active.
Creating scope :fetched_state. Overwriting existing method ArticleDir.fetched_state.
(1.7ms) SELECT COUNT(*) AS count_all,
article_commons.state AS article_commons_state, sengines.name
AS sengines_name FROM article_commons INNER JOIN
directory_keywords ON directory_keywords.article_dir_id =
article_commons.id INNER JOIN keywords ON keywords.id =
directory_keywords.keyword_id INNER JOIN sengines ON
sengines.id = article_commons.sengine_id AND sengines.type
= 'ArticleEngine' WHERE article_commons.type = 'ArticleDir' AND keywords.id IN (1217) AND article_commons.active = TRUE GROUP
BY article_commons.state, sengines.name
=> {["expired", "data..."]=>1, ["fetched", "data..."]=>83, ["sourced", " data..."]=>81}
I've seen one other reference to this issue:
https://github.com/rails/rails/issues/31234
where it was suggested that the message related to overwriting a Kernel method.
I've checked the Kernel and no such methods exist on the Kernel in the first place to overwrite:
irb(main):002:0> Kernel.methods.grep(/active/)
=> []
irb(main):004:0> Kernel.methods.grep(/fetched_state/)
=> []
I am assuming that the message means what it seems to imply - arel / rails is somehow overwriting those two scopes on the model.
If so, why? and what do I do about it?
This can happen when you have something such as an enum that add scopes to the model.
If, in your model, you had an enum with :active as one of the values, e.g.:
enum status: [ :active, :archived ]
to go along with your explicit scope, you would see this warning.

Difference between two files view in HTML using Java or any jar

I want to write a script which compare two files in java and see there difference in html page ( side by side ), can someone help me out how to write ( where to start). I am pulling my hair out for this....
I want to use this script in beanshell postprocessor so that I can compare the standard output files with result files easily
I don't think you should be asking people for writing code for you here, consider hiring a freelancer instead.
Alternatively you can use the following approach:
Add JSR223 Assertion as a child of the request which you would like to fail if files won't be equal
Put the following code into "Script" area:
def file1 = new File('/path/to/file1')
def file2 = new File('/path/to/file2')
def file1Lines = file1.readLines('UTF-8')
def file2Lines = file2.readLines('UTF-8')
if (file1Lines.size() != file2Lines.size()) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Files size is different, omitting line-by-line compare')
} else {
def differences = new StringBuilder()
file1Lines.eachWithIndex {
String file1Line, int number ->
String file2Line = file2Lines.get(number)
if (!file1Line.equals(file2Line)) {
differences.append('Difference # ').append(number).append('. Expected: ')
.append(file1Line).append('. Actual: ' + file2Line)
differences.append(System.getProperty('line.separator'))
}
}
if (differences.toString().length() > 0) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage(differences.toString())
}
}
If there will be differences in files content you will see them listed one by one in the JSR223 Assertion
See Scripting JMeter Assertions in Groovy - A Tutorial for more details.

How to set default css classes for all built-in form widgets in Django

Short version: is it possible to define a set of default css classes that Django should use whenever rendering a form ?
Long version:
The context is as follows: I would like to use the css classes defined in the w3.css framework for all my forms (http://www.w3schools.com/w3css/default.asp). I have seen that it is possible to do that in Django at form class definition or at form rendering, but it requires in both cases an explicit declaration of all the form fields. That means that I loose all the benefit of automatic form generation for ModelForms. I would like something as follows instead:
Define somewhere (e.g. in the settings file) a default mapping between form fields / widgets and css classes, e.g. 'textinput': 'my_default_css_class_for_text_inputs'
By default, for all automatic generation and rendering of forms, the default css classes defined in (1) are used, with no or minimal modification of the existing form classes
For specific forms, I can overload the defaults with other values
As far as I've understood, such behaviour is not possible in django. The crispy-forms package seems to go in that direction, but it seems to do much more than just that, and I am not sure that I want all the extra complexity (I'm still a newbie around here). An alternative would be to use javascript to add the classes on the client side. It looks like an ugly bad practice to me.
Could anyone confirm my understanding of this issue and point me towards elegant solutions, if any ?
Thanks !
Jonathan
I've managed to find the answer to my question and I'm posting it here for posterity. For the label class, I had some inspiration from here and here (answer from user2732686). The first link suggests to redefine the label_tag method of the BoundField class at run-time. It's a less verbose solution than the one suggested in the 2nd link, but at the cost of a project-wide hack, which I would not recommend. Here, I follow Django's subclassing mania, as suggested in the 2nd link for the labels.
In the projects settings.py, add:
# Default css classes for widgets and labels
DEFAULT_CSS = {
'error': 'w3-panel w3-red', # displayed in the label
'errorlist': 'w3-padding-8 w3-red', # encloses the error list
'required': 'w3-text-indigo', # used in the label and label + input enclosing box. NB: w3-validate only works if the input precedes the label!
'label': 'w3-label',
'Textarea': 'w3-input w3-border',
'TextInput': 'w3-input w3-border',
'Select': 'w3-select w3-border',
}
NB: apart from the 4 first keys, the keys must match Django's widget names.
In your forms.py (or elsewhere), add:
from django.forms import ModelForm, inlineformset_factory, Form, BoundField
from django.forms.utils import ErrorList
from django.utils.html import format_html, force_text
from django.conf import settings
class CustErrorList(ErrorList):
# custom error list format to use defcss
def __str__(self):
return self.as_div()
def as_div(self):
if not self:
return ''
return format_html('<div class="{}">{}</div>',
settings.DEFAULT_CSS['errorlist'],
' '.join( [ force_text(e) for e in self ] )
)
class CustBoundField(BoundField):
# overload label_tag to include default css classes for labels
def label_tag(self, contents=None, attrs=None, label_suffix=None):
newcssclass = settings.DEFAULT_CSS['label']
if attrs is None:
attrs = {}
elif 'class' in attrs:
newcssclass = ' '.join( [ attrs['class'], newcssclass ] ) # NB: order has no impact here (but it does in the style sheet)
attrs.update( { 'class': newcssclass } )
# return the output of the original method with the modified attrs
return super( CustBoundField, self ).label_tag( contents, attrs, label_suffix )
def custinit(self, subclass, *args, **kwargs):
# overload Form or ModelForm inits, to use default CSS classes for widgets
super( subclass, self ).__init__(*args, **kwargs)
self.error_class = CustErrorList # change the default error class
# Loop on fields and add css classes
# Warning: must loop on fields, not on boundfields, otherwise inline_formsets break
for field in self.fields.values():
thiswidget = field.widget
if thiswidget .is_hidden:
continue
newcssclass = settings.DEFAULT_CSS[ thiswidget.__class__.__name__ ]
thisattrs = thiswidget.attrs
if 'class' in thisattrs:
newcssclass = ' '.join( [ thisattrs['class'], newcssclass ] ) # NB: order has no impact here (but it does in the style sheet)
thisattrs.update( { 'class': newcssclass } )
def custgetitem(self, name):
# Overload of Form getitem to use the custom BoundField with
# css-classed labels. Everything here is just a copy of django's version,
# apart from the call to CustBoundField
try:
field = self.fields[name]
except KeyError:
raise KeyError(
"Key '%s' not found in '%s'. Choices are: %s." % (
name,
self.__class__.__name__,
', '.join(sorted(f for f in self.fields)),
)
)
if name not in self._bound_fields_cache:
self._bound_fields_cache[name] = CustBoundField( self, field, name )
# In the original version, field.get_bound_field is called, but
# this method only calls BoundField. It is much easier to
# subclass BoundField and call it directly here
return self._bound_fields_cache[name]
class DefaultCssModelForm(ModelForm):
# Defines the new reference ModelForm, with default css classes
error_css_class = settings.DEFAULT_CSS['error']
required_css_class = settings.DEFAULT_CSS['required']
def __init__(self, *args, **kwargs):
custinit(self, DefaultCssModelForm, *args, **kwargs)
def __getitem__(self, name):
return custgetitem(self, name)
class DefaultCssForm(Form):
# Defines the new reference Form, with default css classes
error_css_class = settings.DEFAULT_CSS['error']
required_css_class = settings.DEFAULT_CSS['required']
def __init__(self, *args, **kwargs):
custinit(self, DefaultCssForm, *args, **kwargs)
def __getitem__(self, name):
return custgetitem(self, name)
NB: replace <MY_PROJECT> with your project name
Then, you simply subclass DefaultCssModelForm and DefaultCssForm instead of ModelForm and Form when defining your forms. For formsets, use these classes as base classes. To illustrate:
class MyForm(DefaultCssModelForm):
class Meta:
model = MyModel
fields = '__all__'
MyFormSet = inlineformset_factory( ..., ..., form=DefaultCssModelForm, ... )

Neo4j - Cypher: mutual object with traversing relationships

I have a small Graph:
CREATE
(Dic1:Dictioniary { name:'Dic1' }),
(Dic2:Dictioniary { name: 'Dic2' }),
(Dic3:Dictioniary { name: 'Dic3' }),
(File1:File { name: 'File1' }),
(File2:File { name: 'File2' }),
(File3:File { name: 'File3' }),
(Dic2)-[:contains]->(Dic1),
(Dic1)-[:contains]->(File1),
(Dic3)-[:contains]->(File2),
(File1)-[:references]->(File3),
(File2)-[:references]->(File3)
I need a cypher query to find out, if for example Dic2 and Dic3 have paths/relations, where they reference the same File.
In this case it would be true; the mutual File is File3.
Thanks for your help
When you are looking for just two dictionaries you can achieve this in a single statement:
MATCH (d2:Dictioniary { name:'Dic2' }),(d3:Dictioniary { name:'Dic3' })
MATCH (d2)-[:contains|references*]->(f:File)<-[:contains|references*]-(d3)
RETURN f
It is quite expensive due to the two unbounded path matches, but it is quite cheap as it is bound from the outset by the two dictionary matches.
If you had an arbitrary number of Dictionaries to test you could do something like:
MATCH (d1:Dictioniary { name:'Dic1' }),(d2:Dictioniary { name:'Dic2' }),(d3:Dictioniary { name:'Dic3' })
WITH [d1,d2,d3] AS ds
MATCH (d)-[:contains|references*]->(f:File)
WHERE d IN ds
WITH f, ds, COLLECT(d) AS fds
WHERE length(ds)= length(fds)
RETURN f
This matches the dictionaries that you are interested in first and for each of them in turn it finds the files that they reference. Importantly the File object is preserved and the Dictionary that referenced it is collected into an array (fds). If we know that we had 3 dictionaries to begin with (length(ds)) and that a given file has the same number of related dictionaries (length(fds)) then all dictionaries must reference it.
Assuming that there may multiple paths to a given File from a given Dictionary then you can insert the DISTINCTmodifier into the second WITH statement:
WITH f, ds, COLLECT(DISTINCT(d)) AS fds

Filtering tab completion in input task implementation

I'm currently implementing a SBT plugin for Gatling.
One of its features will be to open the last generated report in a new browser tab from SBT.
As each run can have a different "simulation ID" (basically a simple string), I'd like to offer tab completion on simulation ids.
An example :
Running the Gatling SBT plugin will produce several folders (named from simulationId + date of report generaation) in target/gatling, for example mysim-20140204234534, myothersim-20140203124534 and yetanothersim-20140204234534.
Let's call the task lastReport.
If someone start typing lastReport my, I'd like to filter out tab-completion to only suggest mysim and myothersim.
Getting the simulation ID is a breeze, but how can help the parser and filter out suggestions so that it only suggest an existing simulation ID ?
To sum up, I'd like to do what testOnly do, in a way : I only want to suggest things that make sense in my context.
Thanks in advance for your answers,
Pierre
Edit : As I got a bit stuck after my latest tries, here is the code of my inputTask, in it's current state :
package io.gatling.sbt
import sbt._
import sbt.complete.{ DefaultParsers, Parser }
import io.gatling.sbt.Utils._
object GatlingTasks {
val lastReport = inputKey[Unit]("Open last report in browser")
val allSimulationIds = taskKey[Set[String]]("List of simulation ids found in reports folder")
val allReports = taskKey[List[Report]]("List of all reports by simulation id and timestamp")
def findAllReports(reportsFolder: File): List[Report] = {
val allDirectories = (reportsFolder ** DirectoryFilter.&&(new PatternFilter(reportFolderRegex.pattern))).get
allDirectories.map(file => (file, reportFolderRegex.findFirstMatchIn(file.getPath).get)).map {
case (file, regexMatch) => Report(file, regexMatch.group(1), regexMatch.group(2))
}.toList
}
def findAllSimulationIds(allReports: Seq[Report]): Set[String] = allReports.map(_.simulationId).distinct.toSet
def openLastReport(allReports: List[Report], allSimulationIds: Set[String]): Unit = {
def simulationIdParser(allSimulationIds: Set[String]): Parser[Option[String]] =
DefaultParsers.ID.examples(allSimulationIds, check = true).?
def filterReportsIfSimulationIdSelected(allReports: List[Report], simulationId: Option[String]): List[Report] =
simulationId match {
case Some(id) => allReports.filter(_.simulationId == id)
case None => allReports
}
Def.inputTaskDyn {
val selectedSimulationId = simulationIdParser(allSimulationIds).parsed
val filteredReports = filterReportsIfSimulationIdSelected(allReports, selectedSimulationId)
val reportsSortedByDate = filteredReports.sorted.map(_.path)
Def.task(reportsSortedByDate.headOption.foreach(file => openInBrowser((file / "index.html").toURI)))
}
}
}
Of course, openReport is called using the results of allReports and allSimulationIds tasks.
I think I'm close to a functioning input task but I'm still missing something...
Def.inputTaskDyn returns a value of type InputTask[T] and doesn't perform any side effects. The result needs to be bound to an InputKey, like lastReport. The return type of openLastReport is Unit, which means that openLastReport will construct a value that will be discarded, effectively doing nothing useful. Instead, have:
def openLastReport(...): InputTask[...] = ...
lastReport := openLastReport(...).evaluated
(Or, the implementation of openLastReport can be inlined into the right hand side of :=)
You probably don't need inputTaskDyn, but just inputTask. You only need inputTaskDyn if you need to return a task. Otherwise, use inputTask and drop the Def.task.

Resources